From 424735d44041fc478b572f973d997829b402153d Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 18 Jun 2018 14:05:24 +0700 Subject: rename subfolder source to src --- src/common/binary.h | 132 ++++++++++ src/common/compiler/tusb_compiler_gcc.h | 137 +++++++++++ src/common/compiler/tusb_compiler_iar.h | 91 +++++++ src/common/timeout_timer.h | 76 ++++++ src/common/tusb_common.h | 273 +++++++++++++++++++++ src/common/tusb_compiler.h | 83 +++++++ src/common/tusb_error.h | 114 +++++++++ src/common/tusb_fifo.c | 280 +++++++++++++++++++++ src/common/tusb_fifo.h | 162 +++++++++++++ src/common/tusb_types.h | 414 ++++++++++++++++++++++++++++++++ src/common/tusb_verify.h | 183 ++++++++++++++ 11 files changed, 1945 insertions(+) create mode 100644 src/common/binary.h create mode 100644 src/common/compiler/tusb_compiler_gcc.h create mode 100644 src/common/compiler/tusb_compiler_iar.h create mode 100644 src/common/timeout_timer.h create mode 100644 src/common/tusb_common.h create mode 100644 src/common/tusb_compiler.h create mode 100644 src/common/tusb_error.h create mode 100644 src/common/tusb_fifo.c create mode 100644 src/common/tusb_fifo.h create mode 100644 src/common/tusb_types.h create mode 100644 src/common/tusb_verify.h (limited to 'src/common') diff --git a/src/common/binary.h b/src/common/binary.h new file mode 100644 index 000000000..3ab87e3f8 --- /dev/null +++ b/src/common/binary.h @@ -0,0 +1,132 @@ +/**************************************************************************/ +/*! + @file binary.h + @author hathach (tinyusb.org) + + @section LICENSE + + Software License Agreement (BSD License) + + Copyright (c) 2013, hathach (tinyusb.org) + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holders nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + INCLUDING NEGLIGENCE OR OTHERWISE ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + This file is part of the tinyusb stack. +*/ +/**************************************************************************/ + +/** \ingroup Group_Common + * \defgroup Group_Binary Binary + * @{ */ + +#ifndef _TUSB_BINARY_H_ +#define _TUSB_BINARY_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +#include +#include +#include "tusb_compiler.h" + +//------------- Bit manipulation -------------// +#define BIT_(n) (1U << (n)) ///< n-th Bit +#define BIT_SET_(x, n) ( (x) | BIT_(n) ) ///< set n-th bit of x to 1 +#define BIT_CLR_(x, n) ( (x) & (~BIT_(n)) ) ///< clear n-th bit of x +#define BIT_TEST_(x, n) ( ((x) & BIT_(n)) ? true : false ) ///< check if n-th bit of x is 1 + +static inline uint32_t bit_set(uint32_t value, uint8_t n) ATTR_CONST ATTR_ALWAYS_INLINE; +static inline uint32_t bit_set(uint32_t value, uint8_t n) +{ + return value | BIT_(n); +} + +static inline uint32_t bit_clear(uint32_t value, uint8_t n) ATTR_CONST ATTR_ALWAYS_INLINE; +static inline uint32_t bit_clear(uint32_t value, uint8_t n) +{ + return value & (~BIT_(n)); +} + +static inline bool bit_test(uint32_t value, uint8_t n) ATTR_CONST ATTR_ALWAYS_INLINE; +static inline bool bit_test(uint32_t value, uint8_t n) +{ + return (value & BIT_(n)) ? true : false; +} + +///< create a mask with n-bit lsb set to 1 +static inline uint32_t bit_mask(uint8_t n) ATTR_CONST ATTR_ALWAYS_INLINE; +static inline uint32_t bit_mask(uint8_t n) +{ + return (n < 32) ? ( BIT_(n) - 1 ) : UINT32_MAX; +} + +static inline uint32_t bit_mask_range(uint8_t start, uint32_t end) ATTR_CONST ATTR_ALWAYS_INLINE; +static inline uint32_t bit_mask_range(uint8_t start, uint32_t end) +{ + return bit_mask(end+1) & ~ bit_mask(start); +} + +static inline uint32_t bit_set_range(uint32_t value, uint8_t start, uint8_t end, uint32_t pattern) ATTR_CONST ATTR_ALWAYS_INLINE; +static inline uint32_t bit_set_range(uint32_t value, uint8_t start, uint8_t end, uint32_t pattern) +{ + return ( value & ~bit_mask_range(start, end) ) | (pattern << start); +} + + +//------------- Binary Constant -------------// +#if defined(__GNUC__) && !defined(__CC_ARM) + +#define BIN8(x) ((uint8_t) (0b##x)) +#define BIN16(b1, b2) ((uint16_t) (0b##b1##b2)) +#define BIN32(b1, b2, b3, b4) ((uint32_t) (0b##b1##b2##b3##b4)) + +#else + +// internal macro of B8, B16, B32 +#define _B8__(x) (((x&0x0000000FUL)?1:0) \ + +((x&0x000000F0UL)?2:0) \ + +((x&0x00000F00UL)?4:0) \ + +((x&0x0000F000UL)?8:0) \ + +((x&0x000F0000UL)?16:0) \ + +((x&0x00F00000UL)?32:0) \ + +((x&0x0F000000UL)?64:0) \ + +((x&0xF0000000UL)?128:0)) + +#define BIN8(d) ((uint8_t) _B8__(0x##d##UL)) +#define BIN16(dmsb,dlsb) (((uint16_t)BIN8(dmsb)<<8) + BIN8(dlsb)) +#define BIN32(dmsb,db2,db3,dlsb) \ + (((uint32_t)BIN8(dmsb)<<24) \ + + ((uint32_t)BIN8(db2)<<16) \ + + ((uint32_t)BIN8(db3)<<8) \ + + BIN8(dlsb)) +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* _TUSB_BINARY_H_ */ + +/** @} */ diff --git a/src/common/compiler/tusb_compiler_gcc.h b/src/common/compiler/tusb_compiler_gcc.h new file mode 100644 index 000000000..c9f716d48 --- /dev/null +++ b/src/common/compiler/tusb_compiler_gcc.h @@ -0,0 +1,137 @@ +/**************************************************************************/ +/*! + @file compiler_gcc.h + @author hathach (tinyusb.org) + + @section LICENSE + + Software License Agreement (BSD License) + + Copyright (c) 2013, hathach (tinyusb.org) + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holders nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + INCLUDING NEGLIGENCE OR OTHERWISE ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + This file is part of the tinyusb stack. +*/ +/**************************************************************************/ + +/** \ingroup Group_Compiler + * \defgroup Group_GCC GNU GCC + * @{ */ + +#ifndef _TUSB_COMPILER_GCC_H_ +#define _TUSB_COMPILER_GCC_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +#define ALIGN_OF(x) __alignof__(x) + +/// Normally, the compiler places the objects it generates in sections like data or bss & function in text. Sometimes, however, you need additional sections, or you need certain particular variables to appear in special sections, for example to map to special hardware. The section attribute specifies that a variable (or function) lives in a particular section +#define ATTR_SECTION(sec_name) __attribute__ (( section(#sec_name) )) + +/// If this attribute is used on a function declaration and a call to such a function is not eliminated through dead code elimination or other optimizations, an error that includes message is diagnosed. This is useful for compile-time checking +#define ATTR_ERROR(Message) __attribute__ ((error(Message))) + +/// If this attribute is used on a function declaration and a call to such a function is not eliminated through dead code elimination or other optimizations, a warning that includes message is diagnosed. This is useful for compile-time checking +#define ATTR_WARNING(Message) __attribute__ ((warning(Message))) + +/** \defgroup Group_VariableAttr Variable Attributes + * @{ */ + +/// This attribute specifies a minimum alignment for the variable or structure field, measured in bytes +#define ATTR_ALIGNED(Bytes) __attribute__ ((aligned(Bytes))) + +/// The packed attribute specifies that a variable or structure field should have the smallest possible alignment—one byte for a variable, and one bit for a field, unless you specify a larger value with the aligned attribute +#define ATTR_PACKED __attribute__ ((packed)) + +#define ATTR_PREPACKED + +#define ATTR_PACKED_STRUCT(x) x __attribute__ ((packed)) +/** @} */ + +/** \defgroup Group_FuncAttr Function Attributes + * @{ */ + +/// Generally, functions are not inlined unless optimization is specified. For functions declared inline, this attribute inlines the function even if no optimization level is specified +#define ATTR_ALWAYS_INLINE __attribute__ ((always_inline)) + +/// The nonnull attribute specifies that some function parameters should be non-null pointers. f the compiler determines that a null pointer is passed in an argument slot marked as non-null, and the -Wnonnull option is enabled, a warning is issued. All pointer arguments are marked as non-null +#define ATTR_NON_NULL __attribute__ ((nonull)) + +/// Many functions have no effects except the return value and their return value depends only on the parameters and/or global variables. Such a function can be subject to common subexpression elimination and loop optimization just as an arithmetic operator would be. These functions should be declared with the attribute pure +#define ATTR_PURE __attribute__ ((pure)) + +/// \brief Many functions do not examine any values except their arguments, and have no effects except the return value. Basically this is just slightly more strict class than the pure attribute below, since function is not allowed to read global memory. +/// Note that a function that has pointer arguments and examines the data pointed to must not be declared const. Likewise, a function that calls a non-const function usually must not be const. It does not make sense for a const function to return void +#define ATTR_CONST __attribute__ ((const)) + +/// The deprecated attribute results in a warning if the function is used anywhere in the source file. This is useful when identifying functions that are expected to be removed in a future version of a program. The warning also includes the location of the declaration of the deprecated function, to enable users to easily find further information about why the function is deprecated, or what they should do instead. Note that the warnings only occurs for uses +#define ATTR_DEPRECATED __attribute__ ((deprecated)) + +/// Same as the deprecated attribute with optional message in the warning +#define ATTR_DEPRECATED_MESS(mess) __attribute__ ((deprecated(mess))) + +/// The weak attribute causes the declaration to be emitted as a weak symbol rather than a global. This is primarily useful in defining library functions that can be overridden in user code +#define ATTR_WEAK __attribute__ ((weak)) + +/// The alias attribute causes the declaration to be emitted as an alias for another symbol, which must be specified +#define ATTR_ALIAS(func) __attribute__ ((alias(#func))) + +/// The weakref attribute marks a declaration as a weak reference. It is equivalent with weak + alias attribute, but require function is static +#define ATTR_WEAKREF(func) __attribute__ ((weakref(#func))) + +/// The warn_unused_result attribute causes a warning to be emitted if a caller of the function with this attribute does not use its return value. This is useful for functions where not checking the result is either a security problem or always a bug +#define ATTR_WARN_UNUSED_RESULT __attribute__ ((warn_unused_result)) + +/// This attribute, attached to a function, means that code must be emitted for the function even if it appears that the function is not referenced. This is useful, for example, when the function is referenced only in inline assembly. +#define ATTR_USED __attribute__ ((used)) + +/// This attribute, attached to a function, means that the function is meant to be possibly unused. GCC does not produce a warning for this function. +#define ATTR_UNUSED __attribute__ ((unused)) + +/** @} */ + +/** \defgroup Group_BuiltinFunc Built-in Functions +* @{ */ + +// TODO mcu specific +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ +#define __n2be(x) __builtin_bswap32(x) ///< built-in function to convert 32-bit from native to Big Endian +#define __be2n(x) __n2be(x) ///< built-in function to convert 32-bit from Big Endian to native + +#define __n2be_16(u16) __builtin_bswap16(u16) +#define __be2n_16(u16) __n2be_16(u16) +#endif + +/** @} */ + +#ifdef __cplusplus + } +#endif + +#endif /* _TUSB_COMPILER_GCC_H_ */ + +/// @} diff --git a/src/common/compiler/tusb_compiler_iar.h b/src/common/compiler/tusb_compiler_iar.h new file mode 100644 index 000000000..1703ea45f --- /dev/null +++ b/src/common/compiler/tusb_compiler_iar.h @@ -0,0 +1,91 @@ +/**************************************************************************/ +/*! + @file compiler_iar.h + @author hathach (tinyusb.org) + + @section LICENSE + + Software License Agreement (BSD License) + + Copyright (c) 2013, hathach (tinyusb.org) + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holders nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + INCLUDING NEGLIGENCE OR OTHERWISE ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + This file is part of the tinyusb stack. +*/ +/**************************************************************************/ + +/** \file + * \brief IAR Compiler + */ + +/** \ingroup Group_Compiler + * \defgroup Group_IAR IAR ARM + * @{ + */ + +#ifndef _TUSB_COMPILER_IAR_H_ +#define _TUSB_COMPILER_IAR_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +#define ALIGN_OF(x) __ALIGNOF__(x) + +#define ATTR_PACKED_STRUCT(x) __packed x +#define ATTR_PREPACKED __packed +#define ATTR_PACKED +//#define ATTR_SECTION(section) _Pragma((#section)) + +#define ATTR_ALIGNED(bytes) _Pragma(XSTRING_(data_alignment=##bytes)) + +#ifndef ATTR_ALWAYS_INLINE +/// Generally, functions are not inlined unless optimization is specified. For functions declared inline, this attribute inlines the function even if no optimization level is specified +#define ATTR_ALWAYS_INLINE error +#endif + +#define ATTR_PURE // TODO IAR pure function attribute +#define ATTR_CONST // TODO IAR const function attribute +#define ATTR_WEAK __weak + +#define ATTR_WARN_UNUSED_RESULT +#define ATTR_USED +#define ATTR_UNUSED + +// built-in function to convert 32-bit Big-Endian to Little-Endian +//#if __LITTLE_ENDIAN__ +#define __be2n __REV +#define __n2be __be2n + +#define __n2be_16(u16) ((uint16_t) __REV16(u16)) +#define __be2n_16(u16) __n2be_16(u16) + +#ifdef __cplusplus + } +#endif + +#endif /* _TUSB_COMPILER_IAR_H_ */ + +/** @} */ diff --git a/src/common/timeout_timer.h b/src/common/timeout_timer.h new file mode 100644 index 000000000..aafc8cce2 --- /dev/null +++ b/src/common/timeout_timer.h @@ -0,0 +1,76 @@ +/**************************************************************************/ +/*! + @file timeout_timer.h + @author hathach (tinyusb.org) + + @section LICENSE + + Software License Agreement (BSD License) + + Copyright (c) 2013, hathach (tinyusb.org) + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holders nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + INCLUDING NEGLIGENCE OR OTHERWISE ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + This file is part of the tinyusb stack. +*/ +/**************************************************************************/ + +/** \ingroup Group_Common Common Files + * \defgroup Group_TimeoutTimer timeout timer + * @{ */ + + +#ifndef _TUSB_TIMEOUT_TTIMER_H_ +#define _TUSB_TIMEOUT_TTIMER_H_ + +#include "tusb_compiler.h" +#include "tusb_hal.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + uint32_t start; + uint32_t interval; +}timeout_timer_t; + +static inline void timeout_set(timeout_timer_t* tt, uint32_t msec) +{ + tt->interval = msec; + tt->start = tusb_hal_millis(); +} + +static inline bool timeout_expired(timeout_timer_t* tt) +{ + return ( tusb_hal_millis() - tt->start ) >= tt->interval; +} + +#ifdef __cplusplus + } +#endif + +#endif /* _TUSB_TIMEOUT_TTIMER_H_ */ + +/** @} */ diff --git a/src/common/tusb_common.h b/src/common/tusb_common.h new file mode 100644 index 000000000..2ac0e2e8b --- /dev/null +++ b/src/common/tusb_common.h @@ -0,0 +1,273 @@ +/**************************************************************************/ +/*! + @file tusb_common.h + @author hathach (tinyusb.org) + + @section LICENSE + + Software License Agreement (BSD License) + + Copyright (c) 2013, hathach (tinyusb.org) + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holders nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + INCLUDING NEGLIGENCE OR OTHERWISE ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + This file is part of the tinyusb stack. +*/ +/**************************************************************************/ + +/** \ingroup Group_Common + * \defgroup Group_CommonH common.h + * @{ */ + +#ifndef _TUSB_COMMON_H_ +#define _TUSB_COMMON_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +//--------------------------------------------------------------------+ +// INCLUDES +//--------------------------------------------------------------------+ + +//------------- Standard Header -------------// +#include +#include +#include +#include +#include + +//------------- TUSB Option Header -------------// +#include "tusb_option.h" + +//------------- General Header -------------// +#include "tusb_compiler.h" +#include "tusb_verify.h" +#include "binary.h" +#include "tusb_error.h" +#include "tusb_hal.h" +#include "tusb_fifo.h" + +//------------- TUSB Header -------------// +#include "tusb_types.h" + +//--------------------------------------------------------------------+ +// MACROS +//--------------------------------------------------------------------+ +#define MAX_OF(a, b) ( (a) > (b) ? (a) : (b) ) +#define MIN_OF(a, b) ( (a) < (b) ? (a) : (b) ) + +#define U16_HIGH_U8(u16) ((uint8_t) (((u16) >> 8) & 0x00ff)) +#define U16_LOW_U8(u16) ((uint8_t) ((u16) & 0x00ff)) +#define U16_TO_U8S_BE(u16) U16_HIGH_U8(u16), U16_LOW_U8(u16) +#define U16_TO_U8S_LE(u16) U16_LOW_U8(u16), U16_HIGH_U8(u16) + +#define U32_B1_U8(u32) ((uint8_t) (((u32) >> 24) & 0x000000ff)) // MSB +#define U32_B2_U8(u32) ((uint8_t) (((u32) >> 16) & 0x000000ff)) +#define U32_B3_U8(u32) ((uint8_t) (((u32) >> 8) & 0x000000ff)) +#define U32_B4_U8(u32) ((uint8_t) ((u32) & 0x000000ff)) // LSB + +#define U32_TO_U8S_BE(u32) U32_B1_U8(u32), U32_B2_U8(u32), U32_B3_U8(u32), U32_B4_U8(u32) +#define U32_TO_U8S_LE(u32) U32_B4_U8(u32), U32_B3_U8(u32), U32_B2_U8(u32), U32_B1_U8(u32) + +//------------- Endian Conversion -------------// +#define ENDIAN_BE(u32) \ + (uint32_t) ( (((u32) & 0xFF) << 24) | (((u32) & 0xFF00) << 8) | (((u32) >> 8) & 0xFF00) | (((u32) >> 24) & 0xFF) ) + +#define ENDIAN_BE16(le16) ((uint16_t) ((U16_LOW_U8(le16) << 8) | U16_HIGH_U8(le16)) ) + +#ifndef __n2be_16 +#define __n2be_16(u16) ((uint16_t) ((U16_LOW_U8(u16) << 8) | U16_HIGH_U8(u16)) ) +#define __be2n_16(u16) __n2be_16(u16) +#endif + +//--------------------------------------------------------------------+ +// INLINE FUNCTION +//--------------------------------------------------------------------+ +#define memclr_(buffer, size) memset((buffer), 0, (size)) +#define varclr_(_var) memclr_(_var, sizeof(*(_var))) +#define arrclr_(_arr) memclr_(_arr, sizeof(_arr)) + +#define arrcount_(_arr) ( sizeof(_arr) / sizeof(_arr[0]) ) + +static inline uint8_t const * descriptor_next(uint8_t const p_desc[]) +{ + return p_desc + p_desc[DESCRIPTOR_OFFSET_LENGTH]; +} + +static inline uint8_t descriptor_typeof(uint8_t const p_desc[]) +{ + return p_desc[DESCRIPTOR_OFFSET_TYPE]; +} + +//------------- Conversion -------------// +/// form an uint32_t from 4 x uint8_t +static inline uint32_t u32_from_u8(uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4) ATTR_ALWAYS_INLINE ATTR_CONST; +static inline uint32_t u32_from_u8(uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4) +{ + return ( ((uint32_t) b1) << 24) + ( ((uint32_t) b2) << 16) + ( ((uint32_t) b3) << 8) + b4; +} + +static inline uint8_t u16_high_u8(uint16_t u16) ATTR_CONST ATTR_ALWAYS_INLINE; +static inline uint8_t u16_high_u8(uint16_t u16) +{ + return (uint8_t) ( ((uint16_t) (u16 >> 8)) & 0x00ff); +} + +static inline uint8_t u16_low_u8(uint16_t u16) ATTR_CONST ATTR_ALWAYS_INLINE; +static inline uint8_t u16_low_u8(uint16_t u16) +{ + return (uint8_t) (u16 & 0x00ff); +} + +static inline uint16_t u16_le2be(uint16_t u16) ATTR_CONST ATTR_ALWAYS_INLINE; +static inline uint16_t u16_le2be(uint16_t u16) +{ + return ((uint16_t)(u16_low_u8(u16) << 8)) | u16_high_u8(u16); +} + +//------------- Min -------------// +static inline uint8_t min8_of(uint8_t x, uint8_t y) ATTR_ALWAYS_INLINE ATTR_CONST; +static inline uint8_t min8_of(uint8_t x, uint8_t y) +{ + return (x < y) ? x : y; +} + +static inline uint16_t min16_of(uint16_t x, uint16_t y) ATTR_ALWAYS_INLINE ATTR_CONST; +static inline uint16_t min16_of(uint16_t x, uint16_t y) +{ + return (x < y) ? x : y; +} + +static inline uint32_t min32_of(uint32_t x, uint32_t y) ATTR_ALWAYS_INLINE ATTR_CONST; +static inline uint32_t min32_of(uint32_t x, uint32_t y) +{ + return (x < y) ? x : y; +} + +//------------- Max -------------// +static inline uint32_t max32_of(uint32_t x, uint32_t y) ATTR_ALWAYS_INLINE ATTR_CONST; +static inline uint32_t max32_of(uint32_t x, uint32_t y) +{ + return (x > y) ? x : y; +} + +static inline uint16_t max16_of(uint16_t x, uint16_t y) ATTR_ALWAYS_INLINE ATTR_CONST; +static inline uint16_t max16_of(uint16_t x, uint16_t y) +{ + return (x > y) ? x : y; +} + +//------------- Align -------------// +static inline uint32_t align32 (uint32_t value) ATTR_ALWAYS_INLINE ATTR_CONST; +static inline uint32_t align32 (uint32_t value) +{ + return (value & 0xFFFFFFE0UL); +} + +static inline uint32_t align16 (uint32_t value) ATTR_ALWAYS_INLINE ATTR_CONST; +static inline uint32_t align16 (uint32_t value) +{ + return (value & 0xFFFFFFF0UL); +} + +static inline uint32_t align_n (uint32_t alignment, uint32_t value) ATTR_ALWAYS_INLINE ATTR_CONST; +static inline uint32_t align_n (uint32_t alignment, uint32_t value) +{ + return value & ((uint32_t) ~(alignment-1)); +} + +static inline uint32_t align4k (uint32_t value) ATTR_ALWAYS_INLINE ATTR_CONST; +static inline uint32_t align4k (uint32_t value) +{ + return (value & 0xFFFFF000UL); +} + +static inline uint32_t offset4k(uint32_t value) ATTR_ALWAYS_INLINE ATTR_CONST; +static inline uint32_t offset4k(uint32_t value) +{ + return (value & 0xFFFUL); +} + +//------------- Mathematics -------------// +static inline uint32_t abs_of(int32_t value) ATTR_ALWAYS_INLINE ATTR_CONST; +static inline uint32_t abs_of(int32_t value) +{ + return (value < 0) ? (-value) : value; +} + + +/// inclusive range checking +static inline bool is_in_range(uint32_t lower, uint32_t value, uint32_t upper) ATTR_ALWAYS_INLINE ATTR_CONST; +static inline bool is_in_range(uint32_t lower, uint32_t value, uint32_t upper) +{ + return (lower <= value) && (value <= upper); +} + +/// exclusive range checking +static inline bool is_in_range_exclusive(uint32_t lower, uint32_t value, uint32_t upper) ATTR_ALWAYS_INLINE ATTR_CONST; +static inline bool is_in_range_exclusive(uint32_t lower, uint32_t value, uint32_t upper) +{ + return (lower < value) && (value < upper); +} + +// TODO use clz +static inline uint8_t log2_of(uint32_t value) ATTR_ALWAYS_INLINE ATTR_CONST; +static inline uint8_t log2_of(uint32_t value) +{ + uint8_t result = 0; // log2 of a value is its MSB's position + + while (value >>= 1) + { + result++; + } + return result; +} + +// return the number of set bits in value +static inline uint8_t cardinality_of(uint32_t value) ATTR_ALWAYS_INLINE ATTR_CONST; +static inline uint8_t cardinality_of(uint32_t value) +{ + // Brian Kernighan's method goes through as many iterations as there are set bits. So if we have a 32-bit word with only + // the high bit set, then it will only go once through the loop + // Published in 1988, the C Programming Language 2nd Ed. (by Brian W. Kernighan and Dennis M. Ritchie) + // mentions this in exercise 2-9. On April 19, 2006 Don Knuth pointed out to me that this method + // "was first published by Peter Wegner in CACM 3 (1960), 322. (Also discovered independently by Derrick Lehmer and + // published in 1964 in a book edited by Beckenbach.)" + uint8_t count; + for (count = 0; value; count++) + { + value &= value - 1; // clear the least significant bit set + } + + return count; +} + +#ifdef __cplusplus + } +#endif + +#endif /* _TUSB_COMMON_H_ */ + +/** @} */ diff --git a/src/common/tusb_compiler.h b/src/common/tusb_compiler.h new file mode 100644 index 000000000..369c3121a --- /dev/null +++ b/src/common/tusb_compiler.h @@ -0,0 +1,83 @@ +/**************************************************************************/ +/*! + @file compiler.h + @author hathach (tinyusb.org) + + @section LICENSE + + Software License Agreement (BSD License) + + Copyright (c) 2013, hathach (tinyusb.org) + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holders nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + INCLUDING NEGLIGENCE OR OTHERWISE ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + This file is part of the tinyusb stack. +*/ +/**************************************************************************/ + +/** \ingroup Group_Common + * \defgroup Group_Compiler Compiler + * \brief Group_Compiler brief + * @{ */ + +#ifndef _TUSB_COMPILER_H_ +#define _TUSB_COMPILER_H_ + +#define STRING_(x) #x ///< stringify without expand +#define XSTRING_(x) STRING_(x) ///< expand then stringify +#define STRING_CONCAT_(a, b) a##b ///< concat without expand +#define XSTRING_CONCAT_(a, b) STRING_CONCAT_(a, b) ///< expand then concat + +//--------------------------------------------------------------------+ +// Compile-time Assert (use VERIFY_STATIC to avoid name conflict) +//--------------------------------------------------------------------+ +#if defined(__ICCARM__) || (__STDC_VERSION__ >= 201112L ) + #define VERIFY_STATIC static_assert +#else + #if defined __COUNTER__ && __COUNTER__ != __COUNTER__ + #define _VERIFY_COUNTER __COUNTER__ + #else + #define _VERIFY_COUNTER __LINE__ + #endif + + #define VERIFY_STATIC(const_expr, _mess) enum { XSTRING_CONCAT_(_verify_static_, _VERIFY_COUNTER) = 1/(!!(const_expr)) } +#endif + +// allow debugger to watch any module-wide variables anywhere +#if CFG_TUSB_DEBUG +#define STATIC_VAR +#else +#define STATIC_VAR static +#endif + + +#if defined(__GNUC__) + #include "compiler/tusb_compiler_gcc.h" +#elif defined __ICCARM__ + #include "compiler/tusb_compiler_iar.h" +#endif + +#endif /* _TUSB_COMPILER_H_ */ + +/// @} diff --git a/src/common/tusb_error.h b/src/common/tusb_error.h new file mode 100644 index 000000000..339f6ced1 --- /dev/null +++ b/src/common/tusb_error.h @@ -0,0 +1,114 @@ +/**************************************************************************/ +/*! + @file tusb_error.h + @author hathach (tinyusb.org) + + @section LICENSE + + Software License Agreement (BSD License) + + Copyright (c) 2013, hathach (tinyusb.org) + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holders nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + This file is part of the tinyusb stack. +*/ +/**************************************************************************/ + +/** \ingroup Group_Common + * \defgroup Group_Error Error Codes + * @{ */ + +#ifndef _TUSB_ERRORS_H_ +#define _TUSB_ERRORS_H_ + +#include "tusb_option.h" + +#ifdef __cplusplus + extern "C" { +#endif + +#define ERROR_ENUM(x) x, +#define ERROR_STRING(x) #x, + +#define ERROR_TABLE(ENTRY) \ + ENTRY(TUSB_ERROR_NONE )\ + ENTRY(TUSB_ERROR_INVALID_PARA )\ + ENTRY(TUSB_ERROR_DEVICE_NOT_READY )\ + ENTRY(TUSB_ERROR_INTERFACE_IS_BUSY )\ + ENTRY(TUSB_ERROR_HCD_FAILED )\ + ENTRY(TUSB_ERROR_HCD_OPEN_PIPE_FAILED )\ + ENTRY(TUSB_ERROR_USBH_MOUNT_DEVICE_NOT_RESPOND )\ + ENTRY(TUSB_ERROR_USBH_MOUNT_CONFIG_DESC_TOO_LONG )\ + ENTRY(TUSB_ERROR_USBH_DESCRIPTOR_CORRUPTED )\ + ENTRY(TUSB_ERROR_USBH_XFER_STALLED )\ + ENTRY(TUSB_ERROR_USBH_XFER_FAILED )\ + ENTRY(TUSB_ERROR_OSAL_TIMEOUT )\ + ENTRY(TUSB_ERROR_OSAL_WAITING ) /* only used by OSAL_NONE in the subtask */ \ + ENTRY(TUSB_ERROR_OSAL_TASK_FAILED )\ + ENTRY(TUSB_ERROR_OSAL_QUEUE_FAILED )\ + ENTRY(TUSB_ERROR_OSAL_SEMAPHORE_FAILED )\ + ENTRY(TUSB_ERROR_OSAL_MUTEX_FAILED )\ + ENTRY(TUSB_ERROR_EHCI_NOT_ENOUGH_QTD )\ + ENTRY(TUSB_ERROR_HIDD_DESCRIPTOR_INTERFACE )\ + ENTRY(TUSB_ERROR_HIDH_NOT_SUPPORTED_PROTOCOL )\ + ENTRY(TUSB_ERROR_HIDH_NOT_SUPPORTED_SUBCLASS )\ + ENTRY(TUSB_ERROR_CDC_UNSUPPORTED_SUBCLASS )\ + ENTRY(TUSB_ERROR_CDC_UNSUPPORTED_PROTOCOL )\ + ENTRY(TUSB_ERROR_CDCH_DEVICE_NOT_MOUNTED )\ + ENTRY(TUSB_ERROR_MSC_UNSUPPORTED_PROTOCOL )\ + ENTRY(TUSB_ERROR_MSCH_UNKNOWN_SCSI_COMMAND )\ + ENTRY(TUSB_ERROR_MSCH_DEVICE_NOT_MOUNTED )\ + ENTRY(TUSB_ERROR_HUB_FEATURE_NOT_SUPPORTED )\ + ENTRY(TUSB_ERROR_DESCRIPTOR_CORRUPTED )\ + ENTRY(TUSB_ERROR_DCD_FAILED )\ + ENTRY(TUSB_ERROR_DCD_CONTROL_REQUEST_NOT_SUPPORT )\ + ENTRY(TUSB_ERROR_DCD_NOT_ENOUGH_QTD )\ + ENTRY(TUSB_ERROR_DCD_OPEN_PIPE_FAILED )\ + ENTRY(TUSB_ERROR_DCD_EDPT_XFER )\ + ENTRY(TUSB_ERROR_NOT_SUPPORTED_YET )\ + ENTRY(TUSB_ERROR_USBD_DEVICE_NOT_CONFIGURED )\ + ENTRY(TUSB_ERROR_NOT_ENOUGH_MEMORY )\ + ENTRY(TUSB_ERROR_FAILED )\ + + +/// \brief Error Code returned +typedef enum +{ + ERROR_TABLE(ERROR_ENUM) + TUSB_ERROR_COUNT +}tusb_error_t; + +#if CFG_TUSB_DEBUG +/// Enum to String for debugging purposes. Only available if \ref CFG_TUSB_DEBUG > 0 +extern char const* const tusb_strerr[TUSB_ERROR_COUNT]; +#endif + +#ifdef __cplusplus + } +#endif + +#endif /* _TUSB_ERRORS_H_ */ + +/** @} */ diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c new file mode 100644 index 000000000..b4bb70b87 --- /dev/null +++ b/src/common/tusb_fifo.c @@ -0,0 +1,280 @@ +/**************************************************************************/ +/*! + @file fifo.c + @author hathach (tinyusb.org) + + @section LICENSE + + Software License Agreement (BSD License) + + Copyright (c) 2018, hathach (tinyusb.org) + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holders nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + INCLUDING NEGLIGENCE OR OTHERWISE ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + This file is part of the tinyusb stack. +*/ +/**************************************************************************/ + +#include "tusb_fifo.h" + +/*------------------------------------------------------------------*/ +/* + *------------------------------------------------------------------*/ +#if CFG_FIFO_MUTEX + +#define mutex_lock_if_needed(_ff) if (_ff->mutex) fifo_mutex_lock(_ff->mutex) +#define mutex_unlock_if_needed(_ff) if (_ff->mutex) fifo_mutex_unlock(_ff->mutex) + +#else + +#define mutex_lock_if_needed(_ff) +#define mutex_unlock_if_needed(_ff) + +#endif + +static inline uint16_t min16_of(uint16_t x, uint16_t y) +{ + return (x < y) ? x : y; +} + +static inline bool fifo_initalized(fifo_t* f) +{ + return (f->buffer != NULL) && (f->depth > 0) && (f->item_size > 0); +} + + +void fifo_config(fifo_t *f, void* buffer, uint16_t depth, uint16_t item_size, bool overwritable) +{ + mutex_lock_if_needed(f); + + f->buffer = (uint8_t*) buffer; + f->depth = depth; + f->item_size = item_size; + f->overwritable = overwritable; + + f->rd_idx = f->wr_idx = f->count = 0; + + mutex_unlock_if_needed(f); +} + + +/******************************************************************************/ +/*! + @brief Read one byte out of the RX buffer. + + This function will return the byte located at the array index of the + read pointer, and then increment the read pointer index. If the read + pointer exceeds the maximum buffer size, it will roll over to zero. + + @param[in] f + Pointer to the FIFO buffer to manipulate + @param[in] p_buffer + Pointer to the place holder for data read from the buffer + + @returns TRUE if the queue is not empty +*/ +/******************************************************************************/ +bool fifo_read(fifo_t* f, void * p_buffer) +{ + if( !fifo_initalized(f) ) return false; + if( fifo_empty(f) ) return false; + + mutex_lock_if_needed(f); + + memcpy(p_buffer, + f->buffer + (f->rd_idx * f->item_size), + f->item_size); + f->rd_idx = (f->rd_idx + 1) % f->depth; + f->count--; + + mutex_unlock_if_needed(f); + + return true; +} + +/******************************************************************************/ +/*! + @brief This function will read n elements into the array index specified by + the write pointer and increment the write index. If the write index + exceeds the max buffer size, then it will roll over to zero. + + @param[in] f + Pointer to the FIFO buffer to manipulate + @param[in] p_data + The pointer to data location + @param[in] count + Number of element that buffer can afford + + @returns number of items read from the FIFO +*/ +/******************************************************************************/ +uint16_t fifo_read_n (fifo_t* f, void * p_buffer, uint16_t count) +{ + if( !fifo_initalized(f) ) return 0; + if( fifo_empty(f) ) return 0; + + /* Limit up to fifo's count */ + count = min16_of(count, f->count); + if( count == 0 ) return 0; + + mutex_lock_if_needed(f); + + /* Could copy up to 2 portions marked as 'x' if queue is wrapped around + * case 1: ....RxxxxW....... + * case 2: xxxxxW....Rxxxxxx + */ +// uint16_t index2upper = min16_of(count, f->count-f->rd_idx); + + uint8_t* p_buf = (uint8_t*) p_buffer; + uint16_t len = 0; + while( (len < count) && fifo_read(f, p_buf) ) + { + len++; + p_buf += f->item_size; + } + + mutex_unlock_if_needed(f); + + return len; +} + +/******************************************************************************/ +/*! + @brief Reads one item without removing it from the FIFO + + @param[in] f + Pointer to the FIFO buffer to manipulate + @param[in] position + Position to read from in the FIFO buffer + @param[in] p_buffer + Pointer to the place holder for data read from the buffer + + @returns TRUE if the queue is not empty +*/ +/******************************************************************************/ +bool fifo_peek_at(fifo_t* f, uint16_t position, void * p_buffer) +{ + if ( !fifo_initalized(f) ) return false; + if ( position >= f->count ) return false; + + // rd_idx is position=0 + uint16_t index = (f->rd_idx + position) % f->depth; + memcpy(p_buffer, + f->buffer + (index * f->item_size), + f->item_size); + + return true; +} + +/******************************************************************************/ +/*! + @brief Write one element into the RX buffer. + + This function will write one element into the array index specified by + the write pointer and increment the write index. If the write index + exceeds the max buffer size, then it will roll over to zero. + + @param[in] f + Pointer to the FIFO buffer to manipulate + @param[in] p_data + The byte to add to the FIFO + + @returns TRUE if the data was written to the FIFO (overwrittable + FIFO will always return TRUE) +*/ +/******************************************************************************/ +bool fifo_write(fifo_t* f, void const * p_data) +{ + if ( !fifo_initalized(f) ) return false; + if ( fifo_full(f) && !f->overwritable ) return false; + + mutex_lock_if_needed(f); + + memcpy( f->buffer + (f->wr_idx * f->item_size), + p_data, + f->item_size); + + f->wr_idx = (f->wr_idx + 1) % f->depth; + + if (fifo_full(f)) + { + f->rd_idx = f->wr_idx; // keep the full state (rd == wr && len = size) + } + else + { + f->count++; + } + + mutex_unlock_if_needed(f); + + return true; +} + +/******************************************************************************/ +/*! + @brief This function will write n elements into the array index specified by + the write pointer and increment the write index. If the write index + exceeds the max buffer size, then it will roll over to zero. + + @param[in] f + Pointer to the FIFO buffer to manipulate + @param[in] p_data + The pointer to data to add to the FIFO + @param[in] count + Number of element + @return Number of written elements +*/ +/******************************************************************************/ +uint16_t fifo_write_n(fifo_t* f, void const * p_data, uint16_t count) +{ + if ( count == 0 ) return 0; + + uint8_t* p_buf = (uint8_t*) p_data; + + uint16_t len = 0; + while( (len < count) && fifo_write(f, p_buf) ) + { + len++; + p_buf += f->item_size; + } + + return len; +} + +/******************************************************************************/ +/*! + @brief Clear the fifo read and write pointers and set length to zero + + @param[in] f + Pointer to the FIFO buffer to manipulate +*/ +/******************************************************************************/ +void fifo_clear(fifo_t *f) +{ + mutex_lock_if_needed(f); + + f->rd_idx = f->wr_idx = f->count = 0; + + mutex_unlock_if_needed(f); +} diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h new file mode 100644 index 000000000..452b1f35f --- /dev/null +++ b/src/common/tusb_fifo.h @@ -0,0 +1,162 @@ +/**************************************************************************/ +/*! + @file fifo.h + @author hathach (tinyusb.org) + + @section LICENSE + + Software License Agreement (BSD License) + + Copyright (c) 2018, hathach (tinyusb.org) + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holders nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + INCLUDING NEGLIGENCE OR OTHERWISE ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + This file is part of the tinyusb stack. +*/ +/**************************************************************************/ + +/** \ingroup Group_Common + * \defgroup group_fifo fifo + * @{ */ + +#ifndef _TUSB_FIFO_H_ +#define _TUSB_FIFO_H_ + +#define CFG_FIFO_MUTEX 0 + +#include +#include +#include + +#ifdef __cplusplus + extern "C" { +#endif + +#if CFG_FIFO_MUTEX + +#include "osal/osal.h" + +#if CFG_TUSB_OS == OPT_OS_NONE +// Since all fifo read/write is done in thread mode, there should be +// no conflict except for osal queue which will be address seperatedly. +// Therefore there may be no need for mutex with internal use of fifo + +#define _ff_mutex_def(mutex) + +#else +#define fifo_mutex_t struct os_mutex + +#define fifo_mutex_lock(m) os_mutex_pend(m, OS_TIMEOUT_NEVER) +#define fifo_mutex_unlock(m) os_mutex_release(m) + +/* Internal use only */ +#define _mutex_declare(m) .mutex = m + +#endif + +#else + +#define _mutex_declare(m) + +#endif + + +/** \struct fifo_t + * \brief Simple Circular FIFO + */ +typedef struct +{ + uint8_t* buffer ; ///< buffer pointer + uint16_t depth ; ///< max items + uint16_t item_size ; ///< size of each item + + volatile uint16_t count ; ///< number of items in queue + volatile uint16_t wr_idx ; ///< write pointer + volatile uint16_t rd_idx ; ///< read pointer + + bool overwritable ; + +#if CFG_FIFO_MUTEX + fifo_mutex_t * const mutex; +#endif + +} fifo_t; + +#define FIFO_DEF(name, ff_depth, type, is_overwritable) /*, irq_mutex)*/ \ + uint8_t name##_buffer[ff_depth*sizeof(type)];\ + fifo_t name = {\ + .buffer = name##_buffer,\ + .depth = ff_depth,\ + .item_size = sizeof(type),\ + .overwritable = is_overwritable,\ + /*.irq = irq_mutex*/\ + _mutex_declare(_mutex)\ + } + +void fifo_clear(fifo_t *f); +void fifo_config(fifo_t *f, void* buffer, uint16_t depth, uint16_t item_size, bool overwritable); + +bool fifo_write (fifo_t* f, void const * p_data); +uint16_t fifo_write_n (fifo_t* f, void const * p_data, uint16_t count); + +bool fifo_read (fifo_t* f, void * p_buffer); +uint16_t fifo_read_n (fifo_t* f, void * p_buffer, uint16_t count); + +bool fifo_peek_at (fifo_t* f, uint16_t position, void * p_buffer); + +static inline bool fifo_peek(fifo_t* f, void * p_buffer) +{ + return fifo_peek_at(f, 0, p_buffer); +} + +static inline bool fifo_empty(fifo_t* f) +{ + return (f->count == 0); +} + +static inline bool fifo_full(fifo_t* f) +{ + return (f->count == f->depth); +} + +static inline uint16_t fifo_count(fifo_t* f) +{ + return f->count; +} + +static inline uint16_t fifo_remaining(fifo_t* f) +{ + return f->depth - f->count; +} + +static inline uint16_t fifo_depth(fifo_t* f) +{ + return f->depth; +} + +#ifdef __cplusplus + } +#endif + +#endif /* _TUSB_FIFO_H_ */ diff --git a/src/common/tusb_types.h b/src/common/tusb_types.h new file mode 100644 index 000000000..f3fc856c3 --- /dev/null +++ b/src/common/tusb_types.h @@ -0,0 +1,414 @@ +/**************************************************************************/ +/*! + @file tusb_types.h + @author hathach (tinyusb.org) + + @section LICENSE + + Software License Agreement (BSD License) + + Copyright (c) 2013, hathach (tinyusb.org) + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holders nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + INCLUDING NEGLIGENCE OR OTHERWISE ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + This file is part of the tinyusb stack. +*/ +/**************************************************************************/ + +/** \ingroup group_usb_definitions + * \defgroup USBDef_Type USB Types + * @{ */ + +#ifndef _TUSB_TYPES_H_ +#define _TUSB_TYPES_H_ + +#include +#include +#include "tusb_compiler.h" + +#ifdef __cplusplus + extern "C" { +#endif + +/*------------------------------------------------------------------*/ +/* CONSTANTS + *------------------------------------------------------------------*/ + +/// defined base on EHCI specs value for Endpoint Speed +typedef enum +{ + TUSB_SPEED_FULL = 0, + TUSB_SPEED_LOW , + TUSB_SPEED_HIGH +}tusb_speed_t; + +/// defined base on USB Specs Endpoint's bmAttributes +typedef enum +{ + TUSB_XFER_CONTROL = 0 , + TUSB_XFER_ISOCHRONOUS , + TUSB_XFER_BULK , + TUSB_XFER_INTERRUPT +}tusb_xfer_type_t; + +typedef enum +{ + TUSB_DIR_OUT = 0, + TUSB_DIR_IN = 1, + + TUSB_DIR_IN_MASK = 0x80 +}tusb_dir_t; + + +/// USB Descriptor Types (section 9.4 table 9-5) +typedef enum +{ + TUSB_DESC_DEVICE = 0x01 , + TUSB_DESC_CONFIGURATION = 0x02 , + TUSB_DESC_STRING = 0x03 , + TUSB_DESC_INTERFACE = 0x04 , + TUSB_DESC_ENDPOINT = 0x05 , + TUSB_DESC_DEVICE_QUALIFIER = 0x06 , + TUSB_DESC_OTHER_SPEED_CONFIG = 0x07 , + TUSB_DESC_INTERFACE_POWER = 0x08 , + TUSB_DESC_OTG = 0x09 , + TUSB_DESC_DEBUG = 0x0A , + TUSB_DESC_INTERFACE_ASSOCIATION = 0x0B , + TUSB_DESC_CLASS_SPECIFIC = 0x24 +}tusb_desc_type_t; + +typedef enum +{ + TUSB_REQ_GET_STATUS =0 , ///< 0 + TUSB_REQ_CLEAR_FEATURE , ///< 1 + TUSB_REQ_RESERVED , ///< 2 + TUSB_REQ_SET_FEATURE , ///< 3 + TUSB_REQ_RESERVED2 , ///< 4 + TUSB_REQ_SET_ADDRESS , ///< 5 + TUSB_REQ_GET_DESCRIPTOR , ///< 6 + TUSB_REQ_SET_DESCRIPTOR , ///< 7 + TUSB_REQ_GET_CONFIGURATION , ///< 8 + TUSB_REQ_SET_CONFIGURATION , ///< 9 + TUSB_REQ_GET_INTERFACE , ///< 10 + TUSB_REQ_SET_INTERFACE , ///< 11 + TUSB_REQ_SYNCH_FRAME ///< 12 +}tusb_request_code_t; + +typedef enum +{ + TUSB_REQ_TYPE_STANDARD = 0, + TUSB_REQ_TYPE_CLASS, + TUSB_REQ_TYPE_VENDOR +} tusb_request_type_t; + +typedef enum +{ + TUSB_REQ_RCPT_DEVICE =0, + TUSB_REQ_RCPT_INTERFACE, + TUSB_REQ_RCPT_ENDPOINT, + TUSB_REQ_RCPT_OTHER +} tusb_request_recipient_t; + +typedef enum +{ + TUSB_CLASS_UNSPECIFIED = 0 , ///< 0 + TUSB_CLASS_AUDIO = 1 , ///< 1 + TUSB_CLASS_CDC = 2 , ///< 2 + TUSB_CLASS_HID = 3 , ///< 3 + TUSB_CLASS_RESERVED_4 = 4 , ///< 4 + TUSB_CLASS_PHYSICAL = 5 , ///< 5 + TUSB_CLASS_IMAGE = 6 , ///< 6 + TUSB_CLASS_PRINTER = 7 , ///< 7 + TUSB_CLASS_MSC = 8 , ///< 8 + TUSB_CLASS_HUB = 9 , ///< 9 + TUSB_CLASS_CDC_DATA = 10 , ///< 10 + TUSB_CLASS_SMART_CARD = 11 , ///< 11 + TUSB_CLASS_RESERVED_12 = 12 , ///< 12 + TUSB_CLASS_CONTENT_SECURITY = 13 , ///< 13 + TUSB_CLASS_VIDEO = 14 , ///< 14 + TUSB_CLASS_PERSONAL_HEALTHCARE = 15 , ///< 15 + TUSB_CLASS_AUDIO_VIDEO = 16 , ///< 16 + + TUSB_CLASS_MAPPED_INDEX_START = 17 , // TODO Map DIAGNOSTIC, WIRELESS_CONTROLLER, MISC, VENDOR_SPECIFIC to this to minimize the array + + TUSB_CLASS_DIAGNOSTIC = 0xDC , + TUSB_CLASS_WIRELESS_CONTROLLER = 0xE0 , + TUSB_CLASS_MISC = 0xEF , + TUSB_CLASS_APPLICATION_SPECIFIC = 0xFE , + TUSB_CLASS_VENDOR_SPECIFIC = 0xFF +}tusb_class_code_t; + +typedef enum +{ + MISC_SUBCLASS_COMMON = 2 +}misc_subclass_type_t; + +typedef enum +{ + MISC_PROTOCOL_IAD = 1 +}misc_protocol_type_t; + +enum { + TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP = BIT_(5), + TUSB_DESC_CONFIG_ATT_SELF_POWER = BIT_(6), + TUSB_DESC_CONFIG_ATT_BUS_POWER = BIT_(7) +}; + +#define TUSB_DESC_CONFIG_POWER_MA(x) ((x)/2) + +/// Device State +typedef enum +{ + TUSB_DEVICE_STATE_UNPLUG = 0 , + TUSB_DEVICE_STATE_ADDRESSED , + TUSB_DEVICE_STATE_CONFIGURED , + TUSB_DEVICE_STATE_SUSPENDED , + + TUSB_DEVICE_STATE_REMOVING , + TUSB_DEVICE_STATE_SAFE_REMOVE , + + TUSB_DEVICE_STATE_INVALID_PARAMETER +}tusb_device_state_t; + +typedef enum +{ + TUSB_EVENT_NONE = 0, + TUSB_EVENT_XFER_COMPLETE, + TUSB_EVENT_XFER_ERROR, + TUSB_EVENT_XFER_STALLED, + + TUSB_EVENT_BUS_RESET, // TODO refractor + TUSB_EVENT_SETUP_RECEIVED, +}tusb_event_t; + +enum { + DESCRIPTOR_OFFSET_LENGTH = 0, + DESCRIPTOR_OFFSET_TYPE = 1 +}; + +enum { + INTERFACE_INVALID_NUMBER = 0xff +}; + +static inline uint8_t std_class_code_to_index(uint8_t std_class_code) +{ + return (std_class_code <= TUSB_CLASS_AUDIO_VIDEO ) ? std_class_code : + (std_class_code == TUSB_CLASS_DIAGNOSTIC ) ? TUSB_CLASS_MAPPED_INDEX_START : + (std_class_code == TUSB_CLASS_WIRELESS_CONTROLLER ) ? TUSB_CLASS_MAPPED_INDEX_START + 1 : + (std_class_code == TUSB_CLASS_MISC ) ? TUSB_CLASS_MAPPED_INDEX_START + 2 : + (std_class_code == TUSB_CLASS_APPLICATION_SPECIFIC ) ? TUSB_CLASS_MAPPED_INDEX_START + 3 : + (std_class_code == TUSB_CLASS_VENDOR_SPECIFIC ) ? TUSB_CLASS_MAPPED_INDEX_START + 4 : 0; +} + +//--------------------------------------------------------------------+ +// STANDARD DESCRIPTORS +//--------------------------------------------------------------------+ + +/// USB Standard Device Descriptor (section 9.6.1, table 9-8) +typedef struct ATTR_PACKED +{ + uint8_t bLength ; ///< Size of this descriptor in bytes. + uint8_t bDescriptorType ; ///< DEVICE Descriptor Type. + uint16_t bcdUSB ; ///< BUSB Specification Release Number in Binary-Coded Decimal (i.e., 2.10 is 210H). This field identifies the release of the USB Specification with which the device and its descriptors are compliant. + + uint8_t bDeviceClass ; ///< Class code (assigned by the USB-IF). \li If this field is reset to zero, each interface within a configuration specifies its own class information and the various interfaces operate independently. \li If this field is set to a value between 1 and FEH, the device supports different class specifications on different interfaces and the interfaces may not operate independently. This value identifies the class definition used for the aggregate interfaces. \li If this field is set to FFH, the device class is vendor-specific. + uint8_t bDeviceSubClass ; ///< Subclass code (assigned by the USB-IF). These codes are qualified by the value of the bDeviceClass field. \li If the bDeviceClass field is reset to zero, this field must also be reset to zero. \li If the bDeviceClass field is not set to FFH, all values are reserved for assignment by the USB-IF. + uint8_t bDeviceProtocol ; ///< Protocol code (assigned by the USB-IF). These codes are qualified by the value of the bDeviceClass and the bDeviceSubClass fields. If a device supports class-specific protocols on a device basis as opposed to an interface basis, this code identifies the protocols that the device uses as defined by the specification of the device class. \li If this field is reset to zero, the device does not use class-specific protocols on a device basis. However, it may use classspecific protocols on an interface basis. \li If this field is set to FFH, the device uses a vendor-specific protocol on a device basis. + uint8_t bMaxPacketSize0 ; ///< Maximum packet size for endpoint zero (only 8, 16, 32, or 64 are valid). For HS devices is fixed to 64. + + uint16_t idVendor ; ///< Vendor ID (assigned by the USB-IF). + uint16_t idProduct ; ///< Product ID (assigned by the manufacturer). + uint16_t bcdDevice ; ///< Device release number in binary-coded decimal. + uint8_t iManufacturer ; ///< Index of string descriptor describing manufacturer. + uint8_t iProduct ; ///< Index of string descriptor describing product. + uint8_t iSerialNumber ; ///< Index of string descriptor describing the device's serial number. + + uint8_t bNumConfigurations ; ///< Number of possible configurations. +} tusb_desc_device_t; + +/// USB Standard Configuration Descriptor (section 9.6.1 table 9-10) */ +typedef struct ATTR_PACKED +{ + uint8_t bLength ; ///< Size of this descriptor in bytes + uint8_t bDescriptorType ; ///< CONFIGURATION Descriptor Type + uint16_t wTotalLength ; ///< Total length of data returned for this configuration. Includes the combined length of all descriptors (configuration, interface, endpoint, and class- or vendor-specific) returned for this configuration. + + uint8_t bNumInterfaces ; ///< Number of interfaces supported by this configuration + uint8_t bConfigurationValue ; ///< Value to use as an argument to the SetConfiguration() request to select this configuration. + uint8_t iConfiguration ; ///< Index of string descriptor describing this configuration + uint8_t bmAttributes ; ///< Configuration characteristics \n D7: Reserved (set to one)\n D6: Self-powered \n D5: Remote Wakeup \n D4...0: Reserved (reset to zero) \n D7 is reserved and must be set to one for historical reasons. \n A device configuration that uses power from the bus and a local source reports a non-zero value in bMaxPower to indicate the amount of bus power required and sets D6. The actual power source at runtime may be determined using the GetStatus(DEVICE) request (see USB 2.0 spec Section 9.4.5). \n If a device configuration supports remote wakeup, D5 is set to one. + uint8_t bMaxPower ; ///< Maximum power consumption of the USB device from the bus in this specific configuration when the device is fully operational. Expressed in 2 mA units (i.e., 50 = 100 mA). +} tusb_desc_configuration_t; + +/// USB Standard Interface Descriptor (section 9.6.1 table 9-12) +typedef struct ATTR_PACKED +{ + uint8_t bLength ; ///< Size of this descriptor in bytes + uint8_t bDescriptorType ; ///< INTERFACE Descriptor Type + + uint8_t bInterfaceNumber ; ///< Number of this interface. Zero-based value identifying the index in the array of concurrent interfaces supported by this configuration. + uint8_t bAlternateSetting ; ///< Value used to select this alternate setting for the interface identified in the prior field + uint8_t bNumEndpoints ; ///< Number of endpoints used by this interface (excluding endpoint zero). If this value is zero, this interface only uses the Default Control Pipe. + uint8_t bInterfaceClass ; ///< Class code (assigned by the USB-IF). \li A value of zero is reserved for future standardization. \li If this field is set to FFH, the interface class is vendor-specific. \li All other values are reserved for assignment by the USB-IF. + uint8_t bInterfaceSubClass ; ///< Subclass code (assigned by the USB-IF). \n These codes are qualified by the value of the bInterfaceClass field. \li If the bInterfaceClass field is reset to zero, this field must also be reset to zero. \li If the bInterfaceClass field is not set to FFH, all values are reserved for assignment by the USB-IF. + uint8_t bInterfaceProtocol ; ///< Protocol code (assigned by the USB). \n These codes are qualified by the value of the bInterfaceClass and the bInterfaceSubClass fields. If an interface supports class-specific requests, this code identifies the protocols that the device uses as defined by the specification of the device class. \li If this field is reset to zero, the device does not use a class-specific protocol on this interface. \li If this field is set to FFH, the device uses a vendor-specific protocol for this interface. + uint8_t iInterface ; ///< Index of string descriptor describing this interface +} tusb_desc_interface_t; + +/// USB Standard Endpoint Descriptor (section 9.6.1 table 9-13) +typedef struct ATTR_PACKED +{ + uint8_t bLength ; ///< Size of this descriptor in bytes + uint8_t bDescriptorType ; ///< ENDPOINT Descriptor Type + + uint8_t bEndpointAddress ; ///< The address of the endpoint on the USB device described by this descriptor. The address is encoded as follows: \n Bit 3...0: The endpoint number \n Bit 6...4: Reserved, reset to zero \n Bit 7: Direction, ignored for control endpoints 0 = OUT endpoint 1 = IN endpoint. + + struct ATTR_PACKED { + uint8_t xfer : 2; + uint8_t sync : 2; + uint8_t usage : 2; + uint8_t : 2; + } bmAttributes ; ///< This field describes the endpoint's attributes when it is configured using the bConfigurationValue. \n Bits 1..0: Transfer Type \n- 00 = Control \n- 01 = Isochronous \n- 10 = Bulk \n- 11 = Interrupt \n If not an isochronous endpoint, bits 5..2 are reserved and must be set to zero. If isochronous, they are defined as follows: \n Bits 3..2: Synchronization Type \n- 00 = No Synchronization \n- 01 = Asynchronous \n- 10 = Adaptive \n- 11 = Synchronous \n Bits 5..4: Usage Type \n- 00 = Data endpoint \n- 01 = Feedback endpoint \n- 10 = Implicit feedback Data endpoint \n- 11 = Reserved \n Refer to Chapter 5 of USB 2.0 specification for more information. \n All other bits are reserved and must be reset to zero. Reserved bits must be ignored by the host. + + struct ATTR_PACKED { + uint16_t size : 11; ///< Maximum packet size this endpoint is capable of sending or receiving when this configuration is selected. \n For isochronous endpoints, this value is used to reserve the bus time in the schedule, required for the per-(micro)frame data payloads. The pipe may, on an ongoing basis, actually use less bandwidth than that reserved. The device reports, if necessary, the actual bandwidth used via its normal, non-USB defined mechanisms. \n For all endpoints, bits 10..0 specify the maximum packet size (in bytes). \n For high-speed isochronous and interrupt endpoints: \n Bits 12..11 specify the number of additional transaction opportunities per microframe: \n- 00 = None (1 transaction per microframe) \n- 01 = 1 additional (2 per microframe) \n- 10 = 2 additional (3 per microframe) \n- 11 = Reserved \n Bits 15..13 are reserved and must be set to zero. + uint16_t hs_period_mult : 2; + uint16_t : 0; + }wMaxPacketSize; + + uint8_t bInterval ; ///< Interval for polling endpoint for data transfers. Expressed in frames or microframes depending on the device operating speed (i.e., either 1 millisecond or 125 us units). \n- For full-/high-speed isochronous endpoints, this value must be in the range from 1 to 16. The bInterval value is used as the exponent for a \f$ 2^(bInterval-1) \f$ value; e.g., a bInterval of 4 means a period of 8 (\f$ 2^(4-1) \f$). \n- For full-/low-speed interrupt endpoints, the value of this field may be from 1 to 255. \n- For high-speed interrupt endpoints, the bInterval value is used as the exponent for a \f$ 2^(bInterval-1) \f$ value; e.g., a bInterval of 4 means a period of 8 (\f$ 2^(4-1) \f$) . This value must be from 1 to 16. \n- For high-speed bulk/control OUT endpoints, the bInterval must specify the maximum NAK rate of the endpoint. A value of 0 indicates the endpoint never NAKs. Other values indicate at most 1 NAK each bInterval number of microframes. This value must be in the range from 0 to 255. \n Refer to Chapter 5 of USB 2.0 specification for more information. +} tusb_desc_endpoint_t; + +/// USB Other Speed Configuration Descriptor (section 9.6.1 table 9-11) +typedef struct ATTR_PACKED +{ + uint8_t bLength ; ///< Size of descriptor + uint8_t bDescriptorType ; ///< Other_speed_Configuration Type + uint16_t wTotalLength ; ///< Total length of data returned + + uint8_t bNumInterfaces ; ///< Number of interfaces supported by this speed configuration + uint8_t bConfigurationValue ; ///< Value to use to select configuration + uint8_t IConfiguration ; ///< Index of string descriptor + uint8_t bmAttributes ; ///< Same as Configuration descriptor + uint8_t bMaxPower ; ///< Same as Configuration descriptor +} tusb_desc_other_speed_t; + +/// USB Device Qualifier Descriptor (section 9.6.1 table 9-9) +typedef struct ATTR_PACKED +{ + uint8_t bLength ; ///< Size of descriptor + uint8_t bDescriptorType ; ///< Device Qualifier Type + uint16_t bcdUSB ; ///< USB specification version number (e.g., 0200H for V2.00) + + uint8_t bDeviceClass ; ///< Class Code + uint8_t bDeviceSubClass ; ///< SubClass Code + uint8_t bDeviceProtocol ; ///< Protocol Code + uint8_t bMaxPacketSize0 ; ///< Maximum packet size for other speed + uint8_t bNumConfigurations ; ///< Number of Other-speed Configurations + uint8_t bReserved ; ///< Reserved for future use, must be zero +} tusb_desc_device_qualifier_t; + +/// USB Interface Association Descriptor (IAD ECN) +typedef struct ATTR_PACKED +{ + uint8_t bLength ; ///< Size of descriptor + uint8_t bDescriptorType ; ///< Other_speed_Configuration Type + + uint8_t bFirstInterface ; ///< Index of the first associated interface. + uint8_t bInterfaceCount ; ///< Total number of associated interfaces. + + uint8_t bFunctionClass ; ///< Interface class ID. + uint8_t bFunctionSubClass ; ///< Interface subclass ID. + uint8_t bFunctionProtocol ; ///< Interface protocol ID. + + uint8_t iFunction ; ///< Index of the string descriptor describing the interface association. +} tusb_desc_interface_assoc_t; + +/// USB Header Descriptor +typedef struct ATTR_PACKED +{ + uint8_t bLength ; ///< Size of this descriptor in bytes + uint8_t bDescriptorType ; ///< Descriptor Type +} tusb_desc_header_t; + +typedef struct ATTR_PACKED +{ + uint8_t bLength ; ///< Size of this descriptor in bytes + uint8_t bDescriptorType ; ///< Descriptor Type + uint16_t unicode_string[]; +} tusb_desc_string_t; + + +/*------------------------------------------------------------------*/ +/* Types + *------------------------------------------------------------------*/ + +typedef struct ATTR_PACKED{ + union { + struct ATTR_PACKED { + uint8_t recipient : 5; ///< Recipient type tusb_request_recipient_t. + uint8_t type : 2; ///< Request type tusb_request_type_t. + uint8_t direction : 1; ///< Direction type. tusb_dir_t + } bmRequestType_bit; + uint8_t bmRequestType; + }; + + uint8_t bRequest; + uint16_t wValue; + uint16_t wIndex; + uint16_t wLength; +} tusb_control_request_t; + +VERIFY_STATIC( sizeof(tusb_control_request_t) == 8, "mostly compiler option issue"); + +// TODO move to somewhere suitable +static inline uint8_t bm_request_type(uint8_t direction, uint8_t type, uint8_t recipient) +{ + return ((uint8_t) (direction << 7)) | ((uint8_t) (type << 5)) | (recipient); +} + +// Get direction from Endpoint address +static inline tusb_dir_t edpt_dir(uint8_t addr) +{ + return (addr & TUSB_DIR_IN_MASK) ? TUSB_DIR_IN : TUSB_DIR_OUT; +} + +// Get Endpoint number from address +static inline uint8_t edpt_number(uint8_t addr) +{ + return addr & (~TUSB_DIR_IN_MASK); +} + +static inline uint8_t edpt_addr(uint8_t num, tusb_dir_t dir) +{ + return num | (dir == TUSB_DIR_IN ? TUSB_DIR_IN_MASK : 0); +} + +#ifdef __cplusplus + } +#endif + +#endif /* _TUSB_TYPES_H_ */ + +/** @} */ diff --git a/src/common/tusb_verify.h b/src/common/tusb_verify.h new file mode 100644 index 000000000..0e1f3b934 --- /dev/null +++ b/src/common/tusb_verify.h @@ -0,0 +1,183 @@ +/**************************************************************************/ +/*! + @file verify.h + @author hathach + + @section LICENSE + + Software License Agreement (BSD License) + + Copyright (c) 2018, hathach (tinyusb.org) + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holders nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +/**************************************************************************/ +#ifndef TUSB_VERIFY_H_ +#define TUSB_VERIFY_H_ + +#include +#include +#include "tusb_option.h" +#include "tusb_compiler.h" + +/*------------------------------------------------------------------*/ +/* This file use an advanced macro technique to mimic the default parameter + * as C++ for the sake of code simplicity. Beware of a headache macro + * manipulation that you are told to stay away. + * + * e.g + * + * - VERIFY( cond ) will return false if cond is false + * - VERIFY( cond, err) will return err instead if cond is false + *------------------------------------------------------------------*/ + +#ifdef __cplusplus + extern "C" { +#endif + + +//--------------------------------------------------------------------+ +// VERIFY Helper +//--------------------------------------------------------------------+ +#if CFG_TUSB_DEBUG >= 1 + #define _MESS_ERR(_err) printf("%s: %d: failed, error = %s\n", __func__, __LINE__, tusb_strerr[_err]) + #define _MESS_FAILED() printf("%s: %d: failed\n", __func__, __LINE__) +#else + #define _MESS_ERR(_err) + #define _MESS_FAILED() +#endif + +// Halt CPU (breakpoint) when hitting error, only apply for Cortex M3, M4, M7 +#if defined(__ARM_ARCH_7M__) || defined (__ARM_ARCH_7EM__) + +#define verify_breakpoint() \ + do {\ + volatile uint32_t* ARM_CM_DHCSR = ((volatile uint32_t*) 0xE000EDF0UL); /* Cortex M CoreDebug->DHCSR */ \ + if ( (*ARM_CM_DHCSR) & 1UL ) __asm("BKPT #0\n"); /* Only halt mcu if debugger is attached */\ + } while(0) + +#else +#define verify_breakpoint() +#endif + +/*------------------------------------------------------------------*/ +/* Macro Generator + *------------------------------------------------------------------*/ + +// Helper to implement optional parameter for VERIFY Macro family +#define GET_3RD_ARG(arg1, arg2, arg3, ...) arg3 +#define GET_4TH_ARG(arg1, arg2, arg3, arg4, ...) arg4 + +/*------------- Generator for VERIFY and VERIFY_HDLR -------------*/ +#define VERIFY_DEFINE(_cond, _handler, _ret) do { if ( !(_cond) ) { _handler; return _ret; } } while(0) + +/*------------- Generator for VERIFY_ERR and VERIFY_ERR_HDLR -------------*/ +#define VERIFY_ERR_DEF2(_error, _handler) \ + do { \ + uint32_t _err = (uint32_t)(_error); \ + if ( 0 != _err ) { _MESS_ERR(_err); _handler; return _err; }\ + } while(0) + +#define VERIFY_ERR_DEF3(_error, _handler, _ret) \ + do { \ + uint32_t _err = (uint32_t)(_error); \ + if ( 0 != _err ) { _MESS_ERR(_err); _handler; return _ret; }\ + } while(0) + + + + +/*------------------------------------------------------------------*/ +/* VERIFY + * - VERIFY_1ARGS : return false if failed + * - VERIFY_2ARGS : return provided value if failed + *------------------------------------------------------------------*/ +#define VERIFY_1ARGS(_cond) VERIFY_DEFINE(_cond, , false) +#define VERIFY_2ARGS(_cond, _ret) VERIFY_DEFINE(_cond, , _ret) + +#define VERIFY(...) GET_3RD_ARG(__VA_ARGS__, VERIFY_2ARGS, VERIFY_1ARGS)(__VA_ARGS__) + + +/*------------------------------------------------------------------*/ +/* VERIFY WITH HANDLER + * - VERIFY_HDLR_2ARGS : execute handler, return false if failed + * - VERIFY_HDLR_3ARGS : execute handler, return provided error if failed + *------------------------------------------------------------------*/ +#define VERIFY_HDLR_2ARGS(_cond, _handler) VERIFY_DEFINE(_cond, _handler, false) +#define VERIFY_HDLR_3ARGS(_cond, _handler, _ret) VERIFY_DEFINE(_cond, _handler, _ret) + +#define VERIFY_HDLR(...) GET_4TH_ARG(__VA_ARGS__, VERIFY_HDLR_3ARGS, VERIFY_HDLR_2ARGS)(__VA_ARGS__) + + +/*------------------------------------------------------------------*/ +/* VERIFY STATUS + * - VERIFY_ERR_1ARGS : return status of condition if failed + * - VERIFY_ERR_2ARGS : return provided status code if failed + *------------------------------------------------------------------*/ +#define VERIFY_ERR_1ARGS(_error) VERIFY_ERR_DEF2(_error, ) +#define VERIFY_ERR_2ARGS(_error, _ret) VERIFY_ERR_DEF3(_error, ,_ret) + +#define VERIFY_ERR(...) GET_3RD_ARG(__VA_ARGS__, VERIFY_ERR_2ARGS, VERIFY_ERR_1ARGS)(__VA_ARGS__) + +/*------------------------------------------------------------------*/ +/* VERIFY STATUS WITH HANDLER + * - VERIFY_ERR_HDLR_2ARGS : execute handler, return status if failed + * - VERIFY_ERR_HDLR_3ARGS : execute handler, return provided error if failed + *------------------------------------------------------------------*/ +#define VERIFY_ERR_HDLR_2ARGS(_error, _handler) VERIFY_ERR_DEF2(_error, _handler) +#define VERIFY_ERR_HDLR_3ARGS(_error, _handler, _ret) VERIFY_ERR_DEF3(_error, _handler, _ret) + +#define VERIFY_ERR_HDLR(...) GET_4TH_ARG(__VA_ARGS__, VERIFY_ERR_HDLR_3ARGS, VERIFY_ERR_HDLR_2ARGS)(__VA_ARGS__) + + + +/*------------------------------------------------------------------*/ +/* ASSERT + * basically VERIFY with verify_breakpoint() as handler + * - 1 arg : return false if failed + * - 2 arg : return error if failed + *------------------------------------------------------------------*/ +#define ASSERT_1ARGS(_cond) VERIFY_DEFINE(_cond, _MESS_FAILED(); verify_breakpoint(), false) +#define ASSERT_2ARGS(_cond, _ret) VERIFY_DEFINE(_cond, _MESS_FAILED(); verify_breakpoint(), _ret) + +#define TU_ASSERT(...) GET_3RD_ARG(__VA_ARGS__, ASSERT_2ARGS, ASSERT_1ARGS)(__VA_ARGS__) + +/*------------------------------------------------------------------*/ +/* ASSERT Error + * basically VERIFY Error with verify_breakpoint() as handler + *------------------------------------------------------------------*/ +#define ASERT_ERR_1ARGS(_error) VERIFY_ERR_DEF2(_error, verify_breakpoint()) +#define ASERT_ERR_2ARGS(_error, _ret) VERIFY_ERR_DEF3(_error, verify_breakpoint(), _ret) + +#define TU_ASSERT_ERR(...) GET_3RD_ARG(__VA_ARGS__, ASERT_ERR_2ARGS, ASERT_ERR_1ARGS)(__VA_ARGS__) + +/*------------------------------------------------------------------*/ +/* ASSERT HDLR + *------------------------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif /* TUSB_VERIFY_H_ */ -- cgit v1.3.1 From f8e7695fe932e79dfb590d96762db68cca1daf0c Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 18 Jun 2018 14:31:15 +0700 Subject: clean up --- src/common/tusb_types.h | 11 ----------- src/device/usbd.c | 2 +- src/host/usbh.c | 10 ++++++++++ 3 files changed, 11 insertions(+), 12 deletions(-) (limited to 'src/common') diff --git a/src/common/tusb_types.h b/src/common/tusb_types.h index f3fc856c3..b50cacb03 100644 --- a/src/common/tusb_types.h +++ b/src/common/tusb_types.h @@ -211,16 +211,6 @@ enum { INTERFACE_INVALID_NUMBER = 0xff }; -static inline uint8_t std_class_code_to_index(uint8_t std_class_code) -{ - return (std_class_code <= TUSB_CLASS_AUDIO_VIDEO ) ? std_class_code : - (std_class_code == TUSB_CLASS_DIAGNOSTIC ) ? TUSB_CLASS_MAPPED_INDEX_START : - (std_class_code == TUSB_CLASS_WIRELESS_CONTROLLER ) ? TUSB_CLASS_MAPPED_INDEX_START + 1 : - (std_class_code == TUSB_CLASS_MISC ) ? TUSB_CLASS_MAPPED_INDEX_START + 2 : - (std_class_code == TUSB_CLASS_APPLICATION_SPECIFIC ) ? TUSB_CLASS_MAPPED_INDEX_START + 3 : - (std_class_code == TUSB_CLASS_VENDOR_SPECIFIC ) ? TUSB_CLASS_MAPPED_INDEX_START + 4 : 0; -} - //--------------------------------------------------------------------+ // STANDARD DESCRIPTORS //--------------------------------------------------------------------+ @@ -363,7 +353,6 @@ typedef struct ATTR_PACKED /*------------------------------------------------------------------*/ /* Types *------------------------------------------------------------------*/ - typedef struct ATTR_PACKED{ union { struct ATTR_PACKED { diff --git a/src/device/usbd.c b/src/device/usbd.c index 6718c0876..74079d215 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -608,7 +608,7 @@ tusb_error_t usbd_open_edpt_pair(uint8_t rhport, tusb_desc_endpoint_t const* p_d TU_ASSERT( dcd_edpt_open(rhport, p_desc_ep), TUSB_ERROR_DCD_OPEN_PIPE_FAILED ); - if ( p_desc_ep->bEndpointAddress & TUSB_DIR_IN_MASK ) + if ( edpt_dir(p_desc_ep->bEndpointAddress) == TUSB_DIR_IN ) { (*ep_in) = p_desc_ep->bEndpointAddress; }else diff --git a/src/host/usbh.c b/src/host/usbh.c index 506135b49..a67bd8d8c 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -242,6 +242,16 @@ static inline tusb_error_t usbh_pipe_control_close(uint8_t dev_addr) // return TUSB_INTERFACE_STATUS_BUSY; //} +static inline uint8_t std_class_code_to_index(uint8_t std_class_code) +{ + return (std_class_code <= TUSB_CLASS_AUDIO_VIDEO ) ? std_class_code : + (std_class_code == TUSB_CLASS_DIAGNOSTIC ) ? TUSB_CLASS_MAPPED_INDEX_START : + (std_class_code == TUSB_CLASS_WIRELESS_CONTROLLER ) ? TUSB_CLASS_MAPPED_INDEX_START + 1 : + (std_class_code == TUSB_CLASS_MISC ) ? TUSB_CLASS_MAPPED_INDEX_START + 2 : + (std_class_code == TUSB_CLASS_APPLICATION_SPECIFIC ) ? TUSB_CLASS_MAPPED_INDEX_START + 3 : + (std_class_code == TUSB_CLASS_VENDOR_SPECIFIC ) ? TUSB_CLASS_MAPPED_INDEX_START + 4 : 0; +} + //--------------------------------------------------------------------+ // USBH-HCD ISR/Callback API //--------------------------------------------------------------------+ -- cgit v1.3.1 From b9f8575e2d0632b2b4a2358cf181c276c49eca2f Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 23 Jun 2018 13:19:36 +0700 Subject: clean up device cdc separate cdc tx & rx bufsize --- examples/device/nrf52840/src/tusb_config.h | 4 +++- examples/obsolete/device/src/tusb_config.h | 4 +++- src/class/cdc/cdc_device.c | 11 +++-------- src/common/tusb_fifo.c | 5 ++++- src/device/usbd.c | 14 +++++++++----- 5 files changed, 22 insertions(+), 16 deletions(-) (limited to 'src/common') diff --git a/examples/device/nrf52840/src/tusb_config.h b/examples/device/nrf52840/src/tusb_config.h index 476ff4bed..aee6099b5 100644 --- a/examples/device/nrf52840/src/tusb_config.h +++ b/examples/device/nrf52840/src/tusb_config.h @@ -72,7 +72,9 @@ *------------------------------------------------------------------*/ // FIFO size of CDC TX and RX -#define CFG_TUD_CDC_BUFSIZE 64 +#define CFG_TUD_CDC_RX_BUFSIZE 64 +#define CFG_TUD_CDC_TX_BUFSIZE 64 + // TX is sent automatically every Start of Frame event. // If not enabled, application must call tud_cdc_flush() periodically diff --git a/examples/obsolete/device/src/tusb_config.h b/examples/obsolete/device/src/tusb_config.h index bdadb2110..3904facbe 100644 --- a/examples/obsolete/device/src/tusb_config.h +++ b/examples/obsolete/device/src/tusb_config.h @@ -77,7 +77,9 @@ *------------------------------------------------------------------*/ // FIFO size of CDC TX and RX -#define CFG_TUD_CDC_BUFSIZE 128 +#define CFG_TUD_CDC_RX_BUFSIZE 128 +#define CFG_TUD_CDC_TX_BUFSIZE 128 + // TX is sent automatically in Start of Frame event. // If not enabled, application must call tud_cdc_flush() periodically diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index ccb15205b..583180fcc 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -67,17 +67,12 @@ typedef struct { // TODO multiple rhport -#if CFG_TUSB_MCU == OPT_MCU_NRF5X -// FIXME nrf52 OUT: Controller ACK data even we didn't prepare transfer -CFG_TUSB_ATTR_USBRAM CFG_TUSB_MEM_ALIGN uint8_t _tmp_rx_buf[600]; -#else -CFG_TUSB_ATTR_USBRAM CFG_TUSB_MEM_ALIGN uint8_t _tmp_rx_buf[64]; -#endif +CFG_TUSB_ATTR_USBRAM CFG_TUSB_MEM_ALIGN uint8_t _tmp_rx_buf[64]; CFG_TUSB_ATTR_USBRAM CFG_TUSB_MEM_ALIGN uint8_t _tmp_tx_buf[64]; -FIFO_DEF(_rx_ff, CFG_TUD_CDC_BUFSIZE, uint8_t, true); -FIFO_DEF(_tx_ff, CFG_TUD_CDC_BUFSIZE, uint8_t, false); +FIFO_DEF(_rx_ff, CFG_TUD_CDC_RX_BUFSIZE, uint8_t, true); +FIFO_DEF(_tx_ff, CFG_TUD_CDC_TX_BUFSIZE, uint8_t, false); //--------------------------------------------------------------------+ // INTERNAL OBJECT & FUNCTION DECLARATION diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index b4bb70b87..d6f34f33f 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -37,6 +37,7 @@ /**************************************************************************/ #include "tusb_fifo.h" +#include "common/tusb_verify.h" // for ASSERT /*------------------------------------------------------------------*/ /* @@ -207,7 +208,9 @@ bool fifo_peek_at(fifo_t* f, uint16_t position, void * p_buffer) bool fifo_write(fifo_t* f, void const * p_data) { if ( !fifo_initalized(f) ) return false; - if ( fifo_full(f) && !f->overwritable ) return false; + +// if ( fifo_full(f) && !f->overwritable ) return false; + TU_ASSERT( !(fifo_full(f) && !f->overwritable) ); mutex_lock_if_needed(f); diff --git a/src/device/usbd.c b/src/device/usbd.c index 0f6cebc6c..a58196583 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -46,10 +46,12 @@ #include "usbd.h" #include "device/usbd_pvt.h" -#define USBD_TASK_QUEUE_DEPTH 16 +#ifndef CFG_TUD_TASK_QUEUE_SZ +#define CFG_TUD_TASK_QUEUE_SZ 16 +#endif -#ifndef CFG_TUD_TASK_STACKSIZE -#define CFG_TUD_TASK_STACKSIZE 150 +#ifndef CFG_TUD_TASK_STACK_SZ +#define CFG_TUD_TASK_STACK_SZ 150 #endif #ifndef CFG_TUD_TASK_PRIO @@ -190,10 +192,10 @@ typedef struct ATTR_ALIGNED(4) VERIFY_STATIC(sizeof(usbd_task_event_t) <= 12, "size is not correct"); -OSAL_TASK_DEF(_usbd_task_def, "usbd", usbd_task, CFG_TUD_TASK_PRIO, CFG_TUD_TASK_STACKSIZE); +OSAL_TASK_DEF(_usbd_task_def, "usbd", usbd_task, CFG_TUD_TASK_PRIO, CFG_TUD_TASK_STACK_SZ); /*------------- event queue -------------*/ -OSAL_QUEUE_DEF(_usbd_qdef, USBD_TASK_QUEUE_DEPTH, usbd_task_event_t); +OSAL_QUEUE_DEF(_usbd_qdef, CFG_TUD_TASK_QUEUE_SZ, usbd_task_event_t); static osal_queue_t _usbd_q; /*------------- control transfer semaphore -------------*/ @@ -547,12 +549,14 @@ void dcd_bus_event(uint8_t rhport, usbd_bus_event_type_t bus_event) case USBD_BUS_EVENT_SOF: { + #if CFG_TUD_CDC_FLUSH_ON_SOF usbd_task_event_t task_event = { .rhport = rhport, .event_id = USBD_EVT_SOF, }; osal_queue_send_isr(_usbd_q, &task_event); + #endif } break; -- cgit v1.3.1 From 1faf0a81e4ef7176f152165fe46ff65b598d09ce Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 2 Jul 2018 17:32:09 +0700 Subject: clean up --- src/common/tusb_common.h | 31 +++++++++++++++++++++++++++++++ src/device/usbd_desc.c | 8 ++++---- src/portable/nordic/nrf5x/hal_nrf5x.c | 15 ++++++++------- 3 files changed, 43 insertions(+), 11 deletions(-) (limited to 'src/common') diff --git a/src/common/tusb_common.h b/src/common/tusb_common.h index 2ac0e2e8b..2b45a50c9 100644 --- a/src/common/tusb_common.h +++ b/src/common/tusb_common.h @@ -102,6 +102,37 @@ #define __be2n_16(u16) __n2be_16(u16) #endif + +/*------------------------------------------------------------------*/ +/* Count number of arguments of __VA_ARGS__ + * - reference https://groups.google.com/forum/#!topic/comp.std.c/d-6Mj5Lko_s + * - _GET_NTH_ARG() takes args >= N (64) but only expand to Nth one (64th) + * - _RSEQ_N() is reverse sequential to N to add padding to have + * Nth position is the same as the number of arguments + * - ##__VA_ARGS__ is used to deal with 0 paramerter (swallows comma) + *------------------------------------------------------------------*/ +#ifndef VA_ARGS_NUM_ + +#define VA_ARGS_NUM_(...) NARG_(_0, ##__VA_ARGS__,_RSEQ_N()) +#define NARG_(...) _GET_NTH_ARG(__VA_ARGS__) +#define _GET_NTH_ARG( \ + _1, _2, _3, _4, _5, _6, _7, _8, _9,_10, \ + _11,_12,_13,_14,_15,_16,_17,_18,_19,_20, \ + _21,_22,_23,_24,_25,_26,_27,_28,_29,_30, \ + _31,_32,_33,_34,_35,_36,_37,_38,_39,_40, \ + _41,_42,_43,_44,_45,_46,_47,_48,_49,_50, \ + _51,_52,_53,_54,_55,_56,_57,_58,_59,_60, \ + _61,_62,_63,N,...) N +#define _RSEQ_N() \ + 62,61,60, \ + 59,58,57,56,55,54,53,52,51,50, \ + 49,48,47,46,45,44,43,42,41,40, \ + 39,38,37,36,35,34,33,32,31,30, \ + 29,28,27,26,25,24,23,22,21,20, \ + 19,18,17,16,15,14,13,12,11,10, \ + 9,8,7,6,5,4,3,2,1,0 +#endif + //--------------------------------------------------------------------+ // INLINE FUNCTION //--------------------------------------------------------------------+ diff --git a/src/device/usbd_desc.c b/src/device/usbd_desc.c index 860b7c55b..e5bb49676 100644 --- a/src/device/usbd_desc.c +++ b/src/device/usbd_desc.c @@ -324,7 +324,7 @@ desc_auto_cfg_t const _desc_auto_config_struct = .bEndpointAddress = EP_CDC_OUT, .bmAttributes = { .xfer = TUSB_XFER_BULK }, .wMaxPacketSize = { .size = EP_CDC_SIZE }, - .bInterval = 0 + .bInterval = 0 }, .ep_in = @@ -352,7 +352,7 @@ desc_auto_cfg_t const _desc_auto_config_struct = .bInterfaceClass = TUSB_CLASS_MSC, .bInterfaceSubClass = MSC_SUBCLASS_SCSI, .bInterfaceProtocol = MSC_PROTOCOL_BOT, - .iInterface = 0x05 + .iInterface = 0 // ITF_NUM_MSC + 3 }, .ep_out = @@ -390,7 +390,7 @@ desc_auto_cfg_t const _desc_auto_config_struct = .bInterfaceClass = TUSB_CLASS_HID, .bInterfaceSubClass = HID_SUBCLASS_BOOT, .bInterfaceProtocol = HID_PROTOCOL_KEYBOARD, - .iInterface = 0x05 + .iInterface = ITF_NUM_HID_KEYBOARD + 3, }, .keyboard_hid = @@ -427,7 +427,7 @@ desc_auto_cfg_t const _desc_auto_config_struct = .bInterfaceClass = TUSB_CLASS_HID, .bInterfaceSubClass = HID_SUBCLASS_BOOT, .bInterfaceProtocol = HID_PROTOCOL_MOUSE, - .iInterface = 0x06 + .iInterface = ITF_NUM_HID_MOUSE+3 }, .mouse_hid = diff --git a/src/portable/nordic/nrf5x/hal_nrf5x.c b/src/portable/nordic/nrf5x/hal_nrf5x.c index 7d89a2e74..f616264f0 100644 --- a/src/portable/nordic/nrf5x/hal_nrf5x.c +++ b/src/portable/nordic/nrf5x/hal_nrf5x.c @@ -74,17 +74,15 @@ void tusb_hal_nrf_power_event(uint32_t event); /* HFCLK helper *------------------------------------------------------------------*/ +#ifdef SOFTDEVICE_PRESENT // check if SD is present and enabled static bool is_sd_enabled(void) { uint8_t sd_en = false; - -#ifdef SOFTDEVICE_PRESENT (void) sd_softdevice_is_enabled(&sd_en); -#endif - return sd_en; } +#endif static bool hfclk_running(void) { @@ -285,9 +283,12 @@ void tusb_hal_nrf_power_event (uint32_t event) nrf_usbd_isosplit_set(NRF_USBD_ISOSPLIT_Half); // Enable interrupt. SOF is used as CDC auto flush - NRF_USBD->INTENSET = USBD_INTEN_USBRESET_Msk | USBD_INTEN_USBEVENT_Msk | - USBD_INTEN_EP0SETUP_Msk | USBD_INTEN_EP0DATADONE_Msk | USBD_INTEN_ENDEPIN0_Msk | USBD_INTEN_ENDEPOUT0_Msk | - USBD_INTEN_EPDATA_Msk | ((CFG_TUD_CDC && CFG_TUD_CDC_FLUSH_ON_SOF) ? USBD_INTEN_SOF_Msk : 0); + NRF_USBD->INTENSET = USBD_INTEN_USBRESET_Msk | USBD_INTEN_USBEVENT_Msk | USBD_INTEN_EPDATA_Msk | + USBD_INTEN_EP0SETUP_Msk | USBD_INTEN_EP0DATADONE_Msk | USBD_INTEN_ENDEPIN0_Msk | USBD_INTEN_ENDEPOUT0_Msk; + +#if CFG_TUD_CDC && CFG_TUD_CDC_FLUSH_ON_SOF + NRF_USBD->INTENSET |= USBD_INTEN_SOF_Msk; +#endif // Enable interrupt, Priorities 0,1,4,5 (nRF52) are reserved for SoftDevice NVIC_SetPriority(USBD_IRQn, USB_NVIC_PRIO); -- cgit v1.3.1 From ec3227b2202b007da1b76c20394b6f4d774f68b6 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 3 Jul 2018 16:39:42 +0700 Subject: add TUD_DESC_STRCONV --- src/common/tusb_types.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/common') diff --git a/src/common/tusb_types.h b/src/common/tusb_types.h index b50cacb03..4b8ef899c 100644 --- a/src/common/tusb_types.h +++ b/src/common/tusb_types.h @@ -394,6 +394,10 @@ static inline uint8_t edpt_addr(uint8_t num, tusb_dir_t dir) return num | (dir == TUSB_DIR_IN ? TUSB_DIR_IN_MASK : 0); } + +// Convert comma-separated string to descriptor unicode format +#define TUD_DESC_STRCONV( ... ) (const uint16_t[]) { (TUSB_DESC_STRING << 8 ) | (2*VA_ARGS_NUM_(__VA_ARGS__) + 2), __VA_ARGS__ } + #ifdef __cplusplus } #endif -- cgit v1.3.1 From 3e66d2d31e21d1ce91bcc4728c929b9bdf3421e8 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 4 Jul 2018 00:22:15 +0700 Subject: rename fifo * to tu_fifo to avoid conflict with other module --- src/class/cdc/cdc_device.c | 22 +++++++-------- src/common/tusb_fifo.c | 44 ++++++++++++++--------------- src/common/tusb_fifo.h | 56 ++++++++++++++++++------------------- src/osal/osal_none.h | 12 ++++---- tests/lpc18xx_43xx/test/test_fifo.c | 20 ++++++------- 5 files changed, 77 insertions(+), 77 deletions(-) (limited to 'src/common') diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index 583180fcc..585c8c685 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -71,8 +71,8 @@ typedef struct { CFG_TUSB_ATTR_USBRAM CFG_TUSB_MEM_ALIGN uint8_t _tmp_rx_buf[64]; CFG_TUSB_ATTR_USBRAM CFG_TUSB_MEM_ALIGN uint8_t _tmp_tx_buf[64]; -FIFO_DEF(_rx_ff, CFG_TUD_CDC_RX_BUFSIZE, uint8_t, true); -FIFO_DEF(_tx_ff, CFG_TUD_CDC_TX_BUFSIZE, uint8_t, false); +TU_FIFO_DEF(_rx_ff, CFG_TUD_CDC_RX_BUFSIZE, uint8_t, true); +TU_FIFO_DEF(_tx_ff, CFG_TUD_CDC_TX_BUFSIZE, uint8_t, false); //--------------------------------------------------------------------+ // INTERNAL OBJECT & FUNCTION DECLARATION @@ -104,18 +104,18 @@ void tud_n_cdc_get_line_coding (uint8_t rhport, cdc_line_coding_t* coding) //--------------------------------------------------------------------+ uint32_t tud_n_cdc_available(uint8_t rhport) { - return fifo_count(&_rx_ff); + return tu_fifo_count(&_rx_ff); } int8_t tud_n_cdc_read_char(uint8_t rhport) { int8_t ch; - return fifo_read(&_rx_ff, &ch) ? ch : (-1); + return tu_fifo_read(&_rx_ff, &ch) ? ch : (-1); } uint32_t tud_n_cdc_read(uint8_t rhport, void* buffer, uint32_t bufsize) { - return fifo_read_n(&_rx_ff, buffer, bufsize); + return tu_fifo_read_n(&_rx_ff, buffer, bufsize); } //--------------------------------------------------------------------+ @@ -124,12 +124,12 @@ uint32_t tud_n_cdc_read(uint8_t rhport, void* buffer, uint32_t bufsize) uint32_t tud_n_cdc_write_char(uint8_t rhport, char ch) { - return fifo_write(&_tx_ff, &ch) ? 1 : 0; + return tu_fifo_write(&_tx_ff, &ch) ? 1 : 0; } uint32_t tud_n_cdc_write(uint8_t rhport, void const* buffer, uint32_t bufsize) { - return fifo_write_n(&_tx_ff, buffer, bufsize); + return tu_fifo_write_n(&_tx_ff, buffer, bufsize); } bool tud_n_cdc_flush (uint8_t rhport) @@ -137,7 +137,7 @@ bool tud_n_cdc_flush (uint8_t rhport) uint8_t edpt = _cdcd_itf[rhport].ep_in; VERIFY( !dcd_edpt_busy(rhport, edpt) ); // skip if previous transfer not complete - uint16_t count = fifo_read_n(&_tx_ff, _tmp_tx_buf, sizeof(_tmp_tx_buf)); + uint16_t count = tu_fifo_read_n(&_tx_ff, _tmp_tx_buf, sizeof(_tmp_tx_buf)); VERIFY( tud_n_cdc_connected(rhport) ); // fifo is empty if not connected @@ -230,8 +230,8 @@ void cdcd_close(uint8_t rhport) // no need to close opened pipe, dcd bus reset will put controller's endpoints to default state memclr_(&_cdcd_itf[rhport], sizeof(cdcd_interface_t)); - fifo_clear(&_rx_ff); - fifo_clear(&_tx_ff); + tu_fifo_clear(&_rx_ff); + tu_fifo_clear(&_tx_ff); } tusb_error_t cdcd_control_request_st(uint8_t rhport, tusb_control_request_t const * p_request) @@ -282,7 +282,7 @@ tusb_error_t cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, tusb_event_t event, u if ( ep_addr == p_cdc->ep_out ) { - fifo_write_n(&_rx_ff, _tmp_rx_buf, xferred_bytes); + tu_fifo_write_n(&_rx_ff, _tmp_rx_buf, xferred_bytes); // preparing for next TU_ASSERT( dcd_edpt_xfer(rhport, p_cdc->ep_out, _tmp_rx_buf, sizeof(_tmp_rx_buf)), TUSB_ERROR_DCD_EDPT_XFER ); diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index d6f34f33f..03c0b63ab 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -1,6 +1,6 @@ /**************************************************************************/ /*! - @file fifo.c + @file tusb_fifo.c @author hathach (tinyusb.org) @section LICENSE @@ -44,8 +44,8 @@ *------------------------------------------------------------------*/ #if CFG_FIFO_MUTEX -#define mutex_lock_if_needed(_ff) if (_ff->mutex) fifo_mutex_lock(_ff->mutex) -#define mutex_unlock_if_needed(_ff) if (_ff->mutex) fifo_mutex_unlock(_ff->mutex) +#define mutex_lock_if_needed(_ff) if (_ff->mutex) tu_fifo_mutex_lock(_ff->mutex) +#define mutex_unlock_if_needed(_ff) if (_ff->mutex) tu_fifo_mutex_unlock(_ff->mutex) #else @@ -59,13 +59,13 @@ static inline uint16_t min16_of(uint16_t x, uint16_t y) return (x < y) ? x : y; } -static inline bool fifo_initalized(fifo_t* f) +static inline bool tu_fifo_initalized(tu_fifo_t* f) { return (f->buffer != NULL) && (f->depth > 0) && (f->item_size > 0); } -void fifo_config(fifo_t *f, void* buffer, uint16_t depth, uint16_t item_size, bool overwritable) +void tu_fifo_config(tu_fifo_t *f, void* buffer, uint16_t depth, uint16_t item_size, bool overwritable) { mutex_lock_if_needed(f); @@ -96,10 +96,10 @@ void fifo_config(fifo_t *f, void* buffer, uint16_t depth, uint16_t item_size, bo @returns TRUE if the queue is not empty */ /******************************************************************************/ -bool fifo_read(fifo_t* f, void * p_buffer) +bool tu_fifo_read(tu_fifo_t* f, void * p_buffer) { - if( !fifo_initalized(f) ) return false; - if( fifo_empty(f) ) return false; + if( !tu_fifo_initalized(f) ) return false; + if( tu_fifo_empty(f) ) return false; mutex_lock_if_needed(f); @@ -130,10 +130,10 @@ bool fifo_read(fifo_t* f, void * p_buffer) @returns number of items read from the FIFO */ /******************************************************************************/ -uint16_t fifo_read_n (fifo_t* f, void * p_buffer, uint16_t count) +uint16_t tu_fifo_read_n (tu_fifo_t* f, void * p_buffer, uint16_t count) { - if( !fifo_initalized(f) ) return 0; - if( fifo_empty(f) ) return 0; + if( !tu_fifo_initalized(f) ) return 0; + if( tu_fifo_empty(f) ) return 0; /* Limit up to fifo's count */ count = min16_of(count, f->count); @@ -149,7 +149,7 @@ uint16_t fifo_read_n (fifo_t* f, void * p_buffer, uint16_t count) uint8_t* p_buf = (uint8_t*) p_buffer; uint16_t len = 0; - while( (len < count) && fifo_read(f, p_buf) ) + while( (len < count) && tu_fifo_read(f, p_buf) ) { len++; p_buf += f->item_size; @@ -174,9 +174,9 @@ uint16_t fifo_read_n (fifo_t* f, void * p_buffer, uint16_t count) @returns TRUE if the queue is not empty */ /******************************************************************************/ -bool fifo_peek_at(fifo_t* f, uint16_t position, void * p_buffer) +bool tu_fifo_peek_at(tu_fifo_t* f, uint16_t position, void * p_buffer) { - if ( !fifo_initalized(f) ) return false; + if ( !tu_fifo_initalized(f) ) return false; if ( position >= f->count ) return false; // rd_idx is position=0 @@ -205,12 +205,12 @@ bool fifo_peek_at(fifo_t* f, uint16_t position, void * p_buffer) FIFO will always return TRUE) */ /******************************************************************************/ -bool fifo_write(fifo_t* f, void const * p_data) +bool tu_fifo_write(tu_fifo_t* f, void const * p_data) { - if ( !fifo_initalized(f) ) return false; + if ( !tu_fifo_initalized(f) ) return false; -// if ( fifo_full(f) && !f->overwritable ) return false; - TU_ASSERT( !(fifo_full(f) && !f->overwritable) ); +// if ( tu_fifo_full(f) && !f->overwritable ) return false; + TU_ASSERT( !(tu_fifo_full(f) && !f->overwritable) ); mutex_lock_if_needed(f); @@ -220,7 +220,7 @@ bool fifo_write(fifo_t* f, void const * p_data) f->wr_idx = (f->wr_idx + 1) % f->depth; - if (fifo_full(f)) + if (tu_fifo_full(f)) { f->rd_idx = f->wr_idx; // keep the full state (rd == wr && len = size) } @@ -249,14 +249,14 @@ bool fifo_write(fifo_t* f, void const * p_data) @return Number of written elements */ /******************************************************************************/ -uint16_t fifo_write_n(fifo_t* f, void const * p_data, uint16_t count) +uint16_t tu_fifo_write_n(tu_fifo_t* f, void const * p_data, uint16_t count) { if ( count == 0 ) return 0; uint8_t* p_buf = (uint8_t*) p_data; uint16_t len = 0; - while( (len < count) && fifo_write(f, p_buf) ) + while( (len < count) && tu_fifo_write(f, p_buf) ) { len++; p_buf += f->item_size; @@ -273,7 +273,7 @@ uint16_t fifo_write_n(fifo_t* f, void const * p_data, uint16_t count) Pointer to the FIFO buffer to manipulate */ /******************************************************************************/ -void fifo_clear(fifo_t *f) +void tu_fifo_clear(tu_fifo_t *f) { mutex_lock_if_needed(f); diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index 452b1f35f..d87b32395 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -1,6 +1,6 @@ /**************************************************************************/ /*! - @file fifo.h + @file tusb_fifo.h @author hathach (tinyusb.org) @section LICENSE @@ -65,10 +65,10 @@ #define _ff_mutex_def(mutex) #else -#define fifo_mutex_t struct os_mutex +#define tu_fifo_mutex_t struct os_mutex -#define fifo_mutex_lock(m) os_mutex_pend(m, OS_TIMEOUT_NEVER) -#define fifo_mutex_unlock(m) os_mutex_release(m) +#define tu_fifo_mutex_lock(m) os_mutex_pend(m, OS_TIMEOUT_NEVER) +#define tu_fifo_mutex_unlock(m) os_mutex_release(m) /* Internal use only */ #define _mutex_declare(m) .mutex = m @@ -82,7 +82,7 @@ #endif -/** \struct fifo_t +/** \struct tu_fifo_t * \brief Simple Circular FIFO */ typedef struct @@ -98,59 +98,59 @@ typedef struct bool overwritable ; #if CFG_FIFO_MUTEX - fifo_mutex_t * const mutex; + tu_fifo_mutex_t * const mutex; #endif -} fifo_t; +} tu_fifo_t; -#define FIFO_DEF(name, ff_depth, type, is_overwritable) /*, irq_mutex)*/ \ - uint8_t name##_buffer[ff_depth*sizeof(type)];\ - fifo_t name = {\ - .buffer = name##_buffer,\ - .depth = ff_depth,\ - .item_size = sizeof(type),\ - .overwritable = is_overwritable,\ +#define TU_FIFO_DEF(_name, _depth, _type, _overwritable) /*, irq_mutex)*/ \ + uint8_t _name##_buf[_depth*sizeof(_type)];\ + tu_fifo_t _name = {\ + .buffer = _name##_buf,\ + .depth = _depth,\ + .item_size = sizeof(_type),\ + .overwritable = _overwritable,\ /*.irq = irq_mutex*/\ _mutex_declare(_mutex)\ } -void fifo_clear(fifo_t *f); -void fifo_config(fifo_t *f, void* buffer, uint16_t depth, uint16_t item_size, bool overwritable); +void tu_fifo_clear(tu_fifo_t *f); +void tu_fifo_config(tu_fifo_t *f, void* buffer, uint16_t depth, uint16_t item_size, bool overwritable); -bool fifo_write (fifo_t* f, void const * p_data); -uint16_t fifo_write_n (fifo_t* f, void const * p_data, uint16_t count); +bool tu_fifo_write (tu_fifo_t* f, void const * p_data); +uint16_t tu_fifo_write_n (tu_fifo_t* f, void const * p_data, uint16_t count); -bool fifo_read (fifo_t* f, void * p_buffer); -uint16_t fifo_read_n (fifo_t* f, void * p_buffer, uint16_t count); +bool tu_fifo_read (tu_fifo_t* f, void * p_buffer); +uint16_t tu_fifo_read_n (tu_fifo_t* f, void * p_buffer, uint16_t count); -bool fifo_peek_at (fifo_t* f, uint16_t position, void * p_buffer); +bool tu_fifo_peek_at (tu_fifo_t* f, uint16_t position, void * p_buffer); -static inline bool fifo_peek(fifo_t* f, void * p_buffer) +static inline bool tu_fifo_peek(tu_fifo_t* f, void * p_buffer) { - return fifo_peek_at(f, 0, p_buffer); + return tu_fifo_peek_at(f, 0, p_buffer); } -static inline bool fifo_empty(fifo_t* f) +static inline bool tu_fifo_empty(tu_fifo_t* f) { return (f->count == 0); } -static inline bool fifo_full(fifo_t* f) +static inline bool tu_fifo_full(tu_fifo_t* f) { return (f->count == f->depth); } -static inline uint16_t fifo_count(fifo_t* f) +static inline uint16_t tu_fifo_count(tu_fifo_t* f) { return f->count; } -static inline uint16_t fifo_remaining(fifo_t* f) +static inline uint16_t tu_fifo_remaining(tu_fifo_t* f) { return f->depth - f->count; } -static inline uint16_t fifo_depth(fifo_t* f) +static inline uint16_t tu_fifo_depth(tu_fifo_t* f) { return f->depth; } diff --git a/src/osal/osal_none.h b/src/osal/osal_none.h index 9bdb047b4..1328d1753 100644 --- a/src/osal/osal_none.h +++ b/src/osal/osal_none.h @@ -130,20 +130,20 @@ static inline osal_task_t osal_task_create(osal_task_def_t* taskdef) //--------------------------------------------------------------------+ // QUEUE API //--------------------------------------------------------------------+ -#define OSAL_QUEUE_DEF(_name, _depth, _type) FIFO_DEF(_name, _depth, _type, false) +#define OSAL_QUEUE_DEF(_name, _depth, _type) TU_FIFO_DEF(_name, _depth, _type, false) -typedef fifo_t osal_queue_def_t; -typedef fifo_t* osal_queue_t; +typedef tu_fifo_t osal_queue_def_t; +typedef tu_fifo_t* osal_queue_t; static inline osal_queue_t osal_queue_create(osal_queue_def_t* qdef) { - fifo_clear(qdef); + tu_fifo_clear(qdef); return (osal_queue_t) qdef; } static inline bool osal_queue_send_isr(osal_queue_t const queue_hdl, void const * data) { - return fifo_write( (fifo_t*) queue_hdl, data); + return tu_fifo_write( (tu_fifo_t*) queue_hdl, data); } #define osal_queue_send osal_queue_send_isr @@ -164,7 +164,7 @@ static inline void osal_queue_flush(osal_queue_t const queue_hdl) return TUSB_ERROR_OSAL_WAITING; \ } else{ \ /*tusb_hal_int_disable_all();*/ \ - fifo_read(queue_hdl, p_data); \ + tu_fifo_read(queue_hdl, p_data); \ /*tusb_hal_int_enable_all();*/ \ *(p_error) = TUSB_ERROR_NONE; \ } \ diff --git a/tests/lpc18xx_43xx/test/test_fifo.c b/tests/lpc18xx_43xx/test/test_fifo.c index 2729644ff..0441680f7 100644 --- a/tests/lpc18xx_43xx/test/test_fifo.c +++ b/tests/lpc18xx_43xx/test/test_fifo.c @@ -40,11 +40,11 @@ #include "fifo.h" #define FIFO_SIZE 10 -FIFO_DEF(ff, FIFO_SIZE, uint8_t, false); +TU_FIFO_DEF(ff, FIFO_SIZE, uint8_t, false); void setUp(void) { - fifo_clear(&ff); + tu_fifo_clear(&ff); } void tearDown(void) @@ -57,13 +57,13 @@ void test_normal(void) for(i=0; i < FIFO_SIZE; i++) { - fifo_write(&ff, &i); + tu_fifo_write(&ff, &i); } for(i=0; i < FIFO_SIZE; i++) { uint8_t c; - fifo_read(&ff, &c); + tu_fifo_read(&ff, &c); TEST_ASSERT_EQUAL(i, c); } } @@ -71,21 +71,21 @@ void test_normal(void) void test_is_empty(void) { uint8_t temp; - TEST_ASSERT_TRUE(fifo_is_empty(&ff)); - fifo_write(&ff, &temp); - TEST_ASSERT_FALSE(fifo_is_empty(&ff)); + TEST_ASSERT_TRUE(tu_fifo_is_empty(&ff)); + tu_fifo_write(&ff, &temp); + TEST_ASSERT_FALSE(tu_fifo_is_empty(&ff)); } void test_is_full(void) { uint8_t i; - TEST_ASSERT_FALSE(fifo_is_full(&ff)); + TEST_ASSERT_FALSE(tu_fifo_is_full(&ff)); for(i=0; i < FIFO_SIZE; i++) { - fifo_write(&ff, &i); + tu_fifo_write(&ff, &i); } - TEST_ASSERT_TRUE(fifo_is_full(&ff)); + TEST_ASSERT_TRUE(tu_fifo_is_full(&ff)); } -- cgit v1.3.1 From 1efb552bfd097a23651bbb5ad29b6d8eb3bc9ccd Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 13 Jul 2018 17:48:26 +0700 Subject: add ep2drv, rename descriptor offset --- src/class/cdc/cdc_device.c | 12 +++---- src/class/cdc/cdc_host.c | 14 ++++---- src/class/hid/hid_device.c | 4 +-- src/class/hid/hid_host.c | 4 +-- src/common/tusb_common.h | 11 +++++-- src/common/tusb_types.h | 4 +-- src/device/usbd.c | 79 +++++++++++++++++++++++++++++++--------------- src/host/usbh.c | 8 ++--- 8 files changed, 85 insertions(+), 51 deletions(-) (limited to 'src/common') diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index 643706269..76526d40b 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -192,31 +192,31 @@ tusb_error_t cdcd_open(uint8_t rhport, tusb_desc_interface_t const * p_interface (*p_length) = sizeof(tusb_desc_interface_t); // Communication Functional Descriptors - while( TUSB_DESC_CLASS_SPECIFIC == p_desc[DESCRIPTOR_OFFSET_TYPE] ) + while( TUSB_DESC_CLASS_SPECIFIC == p_desc[DESC_OFFSET_TYPE] ) { - (*p_length) += p_desc[DESCRIPTOR_OFFSET_LENGTH]; + (*p_length) += p_desc[DESC_OFFSET_LEN]; p_desc = descriptor_next(p_desc); } - if ( TUSB_DESC_ENDPOINT == p_desc[DESCRIPTOR_OFFSET_TYPE]) + if ( TUSB_DESC_ENDPOINT == p_desc[DESC_OFFSET_TYPE]) { // notification endpoint if any TU_ASSERT( dcd_edpt_open(rhport, (tusb_desc_endpoint_t const *) p_desc), TUSB_ERROR_DCD_OPEN_PIPE_FAILED); p_cdc->ep_notif = ((tusb_desc_endpoint_t const *) p_desc)->bEndpointAddress; - (*p_length) += p_desc[DESCRIPTOR_OFFSET_LENGTH]; + (*p_length) += p_desc[DESC_OFFSET_LEN]; p_desc = descriptor_next(p_desc); } //------------- Data Interface (if any) -------------// - if ( (TUSB_DESC_INTERFACE == p_desc[DESCRIPTOR_OFFSET_TYPE]) && + if ( (TUSB_DESC_INTERFACE == p_desc[DESC_OFFSET_TYPE]) && (TUSB_CLASS_CDC_DATA == ((tusb_desc_interface_t const *) p_desc)->bInterfaceClass) ) { // p_cdc->itf_num = p_cdc->ep_count += ((tusb_desc_interface_t const *) p_desc)->bNumEndpoints; // next to endpoint descritpor - (*p_length) += p_desc[DESCRIPTOR_OFFSET_LENGTH]; + (*p_length) += p_desc[DESC_OFFSET_LEN]; p_desc = descriptor_next(p_desc); // Open endpoint pair with usbd helper diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index bd5b5e32c..6950759d1 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -167,32 +167,32 @@ tusb_error_t cdch_open_subtask(uint8_t dev_addr, tusb_desc_interface_t const *p_ //------------- Communication Interface -------------// (*p_length) = sizeof(tusb_desc_interface_t); - while( TUSB_DESC_CLASS_SPECIFIC == p_desc[DESCRIPTOR_OFFSET_TYPE] ) + while( TUSB_DESC_CLASS_SPECIFIC == p_desc[DESC_OFFSET_TYPE] ) { // Communication Functional Descriptors if ( CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT == cdc_functional_desc_typeof(p_desc) ) { // save ACM bmCapabilities p_cdc->acm_capability = ((cdc_desc_func_acm_t const *) p_desc)->bmCapabilities; } - (*p_length) += p_desc[DESCRIPTOR_OFFSET_LENGTH]; + (*p_length) += p_desc[DESC_OFFSET_LEN]; p_desc = descriptor_next(p_desc); } - if ( TUSB_DESC_ENDPOINT == p_desc[DESCRIPTOR_OFFSET_TYPE]) + if ( TUSB_DESC_ENDPOINT == p_desc[DESC_OFFSET_TYPE]) { // notification endpoint if any p_cdc->pipe_notification = hcd_pipe_open(dev_addr, (tusb_desc_endpoint_t const *) p_desc, TUSB_CLASS_CDC); - (*p_length) += p_desc[DESCRIPTOR_OFFSET_LENGTH]; + (*p_length) += p_desc[DESC_OFFSET_LEN]; p_desc = descriptor_next(p_desc); TU_ASSERT(pipehandle_is_valid(p_cdc->pipe_notification), TUSB_ERROR_HCD_OPEN_PIPE_FAILED); } //------------- Data Interface (if any) -------------// - if ( (TUSB_DESC_INTERFACE == p_desc[DESCRIPTOR_OFFSET_TYPE]) && + if ( (TUSB_DESC_INTERFACE == p_desc[DESC_OFFSET_TYPE]) && (TUSB_CLASS_CDC_DATA == ((tusb_desc_interface_t const *) p_desc)->bInterfaceClass) ) { - (*p_length) += p_desc[DESCRIPTOR_OFFSET_LENGTH]; + (*p_length) += p_desc[DESC_OFFSET_LEN]; p_desc = descriptor_next(p_desc); // data endpoints expected to be in pairs @@ -208,7 +208,7 @@ tusb_error_t cdch_open_subtask(uint8_t dev_addr, tusb_desc_interface_t const *p_ (*p_pipe_hdl) = hcd_pipe_open(dev_addr, p_endpoint, TUSB_CLASS_CDC); TU_ASSERT ( pipehandle_is_valid(*p_pipe_hdl), TUSB_ERROR_HCD_OPEN_PIPE_FAILED ); - (*p_length) += p_desc[DESCRIPTOR_OFFSET_LENGTH]; + (*p_length) += p_desc[DESC_OFFSET_LEN]; p_desc = descriptor_next( p_desc ); } } diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index bc2ee8c64..9f22697a6 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -259,12 +259,12 @@ tusb_error_t hidd_open(uint8_t rhport, tusb_desc_interface_t const * p_interface uint8_t const *p_desc = (uint8_t const *) p_interface_desc; //------------- HID descriptor -------------// - p_desc += p_desc[DESCRIPTOR_OFFSET_LENGTH]; + p_desc += p_desc[DESC_OFFSET_LEN]; tusb_hid_descriptor_hid_t const *p_desc_hid = (tusb_hid_descriptor_hid_t const *) p_desc; TU_ASSERT(HID_DESC_TYPE_HID == p_desc_hid->bDescriptorType, TUSB_ERROR_HIDD_DESCRIPTOR_INTERFACE); //------------- Endpoint Descriptor -------------// - p_desc += p_desc[DESCRIPTOR_OFFSET_LENGTH]; + p_desc += p_desc[DESC_OFFSET_LEN]; tusb_desc_endpoint_t const *p_desc_endpoint = (tusb_desc_endpoint_t const *) p_desc; TU_ASSERT(TUSB_DESC_ENDPOINT == p_desc_endpoint->bDescriptorType, TUSB_ERROR_HIDD_DESCRIPTOR_INTERFACE); diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 69f86ee0b..fe0b7748b 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -186,12 +186,12 @@ tusb_error_t hidh_open_subtask(uint8_t dev_addr, tusb_desc_interface_t const *p_ uint8_t const *p_desc = (uint8_t const *) p_interface_desc; //------------- HID descriptor -------------// - p_desc += p_desc[DESCRIPTOR_OFFSET_LENGTH]; + p_desc += p_desc[DESC_OFFSET_LEN]; tusb_hid_descriptor_hid_t const *p_desc_hid = (tusb_hid_descriptor_hid_t const *) p_desc; TU_ASSERT(HID_DESC_TYPE_HID == p_desc_hid->bDescriptorType, TUSB_ERROR_INVALID_PARA); //------------- Endpoint Descriptor -------------// - p_desc += p_desc[DESCRIPTOR_OFFSET_LENGTH]; + p_desc += p_desc[DESC_OFFSET_LEN]; tusb_desc_endpoint_t const * p_endpoint_desc = (tusb_desc_endpoint_t const *) p_desc; TU_ASSERT(TUSB_DESC_ENDPOINT == p_endpoint_desc->bDescriptorType, TUSB_ERROR_INVALID_PARA); diff --git a/src/common/tusb_common.h b/src/common/tusb_common.h index 2b45a50c9..ddfceabdb 100644 --- a/src/common/tusb_common.h +++ b/src/common/tusb_common.h @@ -144,12 +144,17 @@ static inline uint8_t const * descriptor_next(uint8_t const p_desc[]) { - return p_desc + p_desc[DESCRIPTOR_OFFSET_LENGTH]; + return p_desc + p_desc[DESC_OFFSET_LEN]; } -static inline uint8_t descriptor_typeof(uint8_t const p_desc[]) +static inline uint8_t descriptor_type(uint8_t const p_desc[]) { - return p_desc[DESCRIPTOR_OFFSET_TYPE]; + return p_desc[DESC_OFFSET_TYPE]; +} + +static inline uint8_t descriptor_len(uint8_t const p_desc[]) +{ + return p_desc[DESC_OFFSET_LEN]; } //------------- Conversion -------------// diff --git a/src/common/tusb_types.h b/src/common/tusb_types.h index 4b8ef899c..65e7cd999 100644 --- a/src/common/tusb_types.h +++ b/src/common/tusb_types.h @@ -203,8 +203,8 @@ typedef enum }tusb_event_t; enum { - DESCRIPTOR_OFFSET_LENGTH = 0, - DESCRIPTOR_OFFSET_TYPE = 1 + DESC_OFFSET_LEN = 0, + DESC_OFFSET_TYPE = 1 }; enum { diff --git a/src/device/usbd.c b/src/device/usbd.c index 504cdf77b..d795e4f9a 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -66,7 +66,10 @@ typedef struct { uint8_t config_num; // map interface number to driver (0xff is invalid) - uint8_t itf2drv[16]; + uint8_t itf2drv[16]; + + // map endpoint to driver ( 0xff is invalid ) + uint8_t ep2drv[2][8]; }usbd_device_t; CFG_TUSB_ATTR_USBRAM CFG_TUSB_MEM_ALIGN uint8_t _usbd_ctrl_buf[CFG_TUD_CTRL_BUFSIZE]; @@ -100,18 +103,6 @@ static usbd_class_driver_t const usbd_class_drivers[] = }, #endif - #if DEVICE_CLASS_HID - { - .class_code = TUSB_CLASS_HID, - .init = hidd_init, - .open = hidd_open, - .control_req_st = hidd_control_request_st, - .xfer_cb = hidd_xfer_cb, - .sof = NULL, - .reset = hidd_reset - }, - #endif - #if CFG_TUD_MSC { .class_code = TUSB_CLASS_MSC, @@ -124,6 +115,19 @@ static usbd_class_driver_t const usbd_class_drivers[] = }, #endif + + #if DEVICE_CLASS_HID + { + .class_code = TUSB_CLASS_HID, + .init = hidd_init, + .open = hidd_open, + .control_req_st = hidd_control_request_st, + .xfer_cb = hidd_xfer_cb, + .sof = NULL, + .reset = hidd_reset + }, + #endif + #if CFG_TUD_CUSTOM_CLASS { .class_code = TUSB_CLASS_VENDOR_SPECIFIC, @@ -191,6 +195,7 @@ static osal_semaphore_def_t _usbd_sem_def; //--------------------------------------------------------------------+ // INTERNAL FUNCTION //--------------------------------------------------------------------+ +static void mark_interface_endpoint(uint8_t const* p_desc, uint16_t desc_len, uint8_t driver_id); static tusb_error_t proc_set_config_req(uint8_t rhport, uint8_t config_number); static uint16_t get_descriptor(uint8_t rhport, tusb_control_request_t const * const p_request, uint8_t const ** pp_buffer); @@ -300,6 +305,7 @@ static void usbd_reset(uint8_t rhport) { varclr_(&_usbd_dev); memset(_usbd_dev.itf2drv, 0xff, sizeof(_usbd_dev.itf2drv)); // invalid mapping + memset(_usbd_dev.ep2drv , 0xff, sizeof(_usbd_dev.ep2drv )); // invalid mapping for (uint8_t i = 0; i < USBD_CLASS_DRIVER_COUNT; i++) { @@ -395,6 +401,7 @@ static tusb_error_t proc_control_request_st(uint8_t rhport, tusb_control_request OSAL_SUBTASK_END } +// Process Set Configure Request // TODO Host (windows) can get HID report descriptor before set configured // may need to open interface before set configured static tusb_error_t proc_set_config_req(uint8_t rhport, uint8_t config_number) @@ -418,33 +425,35 @@ static tusb_error_t proc_set_config_req(uint8_t rhport, uint8_t config_number) while( p_desc < desc_cfg + cfg_len ) { - if ( TUSB_DESC_INTERFACE_ASSOCIATION == p_desc[DESCRIPTOR_OFFSET_TYPE]) + if ( TUSB_DESC_INTERFACE_ASSOCIATION == descriptor_type(p_desc) ) { - p_desc += p_desc[DESCRIPTOR_OFFSET_LENGTH]; // ignore Interface Association + p_desc = descriptor_next(p_desc); // ignore Interface Association }else { - TU_ASSERT( TUSB_DESC_INTERFACE == p_desc[DESCRIPTOR_OFFSET_TYPE], TUSB_ERROR_NOT_SUPPORTED_YET ); + TU_ASSERT( TUSB_DESC_INTERFACE == descriptor_type(p_desc), TUSB_ERROR_NOT_SUPPORTED_YET ); tusb_desc_interface_t* p_desc_itf = (tusb_desc_interface_t*) p_desc; uint8_t const class_code = p_desc_itf->bInterfaceClass; // Check if class is supported - uint8_t drid; - for (drid = 0; drid < USBD_CLASS_DRIVER_COUNT; drid++) + uint8_t drv_id; + for (drv_id = 0; drv_id < USBD_CLASS_DRIVER_COUNT; drv_id++) { - if ( usbd_class_drivers[drid].class_code == class_code ) break; + if ( usbd_class_drivers[drv_id].class_code == class_code ) break; } - TU_ASSERT( drid < USBD_CLASS_DRIVER_COUNT, TUSB_ERROR_NOT_SUPPORTED_YET ); + TU_ASSERT( drv_id < USBD_CLASS_DRIVER_COUNT, TUSB_ERROR_NOT_SUPPORTED_YET ); // Interface number must not be used TU_ASSERT( 0xff == _usbd_dev.itf2drv[p_desc_itf->bInterfaceNumber], TUSB_ERROR_FAILED); - _usbd_dev.itf2drv[p_desc_itf->bInterfaceNumber] = drid; + _usbd_dev.itf2drv[p_desc_itf->bInterfaceNumber] = drv_id; + + uint16_t len=0; + TU_ASSERT_ERR( usbd_class_drivers[drv_id].open( rhport, p_desc_itf, &len ) ); + TU_ASSERT( len >= sizeof(tusb_desc_interface_t), TUSB_ERROR_FAILED ); - uint16_t length=0; - TU_ASSERT_ERR( usbd_class_drivers[drid].open( rhport, p_desc_itf, &length ) ); + mark_interface_endpoint(p_desc, len, drv_id); - TU_ASSERT( length >= sizeof(tusb_desc_interface_t), TUSB_ERROR_FAILED ); - p_desc += length; + p_desc += len; // next interface } } @@ -454,6 +463,7 @@ static tusb_error_t proc_set_config_req(uint8_t rhport, uint8_t config_number) return TUSB_ERROR_NONE; } +// return len of descriptor and change pointer to descriptor's buffer static uint16_t get_descriptor(uint8_t rhport, tusb_control_request_t const * const p_request, uint8_t const ** pp_buffer) { (void) rhport; @@ -514,6 +524,25 @@ static uint16_t get_descriptor(uint8_t rhport, tusb_control_request_t const * co return len; } +// Helper marking endpoint of interface belongs to class driver +static void mark_interface_endpoint(uint8_t const* p_desc, uint16_t desc_len, uint8_t driver_id) +{ + uint16_t len = 0; + + while( len < desc_len ) + { + if ( TUSB_DESC_ENDPOINT == descriptor_type(p_desc) ) + { + uint8_t const ep_addr = ((tusb_desc_endpoint_t const*) p_desc)->bEndpointAddress; + + _usbd_dev.ep2drv[ edpt_dir(ep_addr) ][ edpt_number(ep_addr) ] = driver_id; + } + + len += descriptor_len(p_desc); + p_desc = descriptor_next(p_desc); + } +} + //--------------------------------------------------------------------+ // USBD-DCD Callback API //--------------------------------------------------------------------+ diff --git a/src/host/usbh.c b/src/host/usbh.c index a67bd8d8c..6d1cd37ad 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -572,9 +572,9 @@ tusb_error_t enumeration_body_subtask(void) while( p_desc < enum_data_buffer + ((tusb_desc_configuration_t*)enum_data_buffer)->wTotalLength ) { // skip until we see interface descriptor - if ( TUSB_DESC_INTERFACE != p_desc[DESCRIPTOR_OFFSET_TYPE] ) + if ( TUSB_DESC_INTERFACE != p_desc[DESC_OFFSET_TYPE] ) { - p_desc += p_desc[DESCRIPTOR_OFFSET_LENGTH]; // skip the descriptor, increase by the descriptor's length + p_desc += p_desc[DESC_OFFSET_LEN]; // skip the descriptor, increase by the descriptor's length }else { static uint8_t class_index; // has to be static as it is used to call class's open_subtask @@ -600,11 +600,11 @@ tusb_error_t enumeration_body_subtask(void) p_desc += length; }else // Interface open failed, for example a subclass is not supported { - p_desc += p_desc[DESCRIPTOR_OFFSET_LENGTH]; // skip this interface, the rest will be skipped by the above loop + p_desc += p_desc[DESC_OFFSET_LEN]; // skip this interface, the rest will be skipped by the above loop } } else // unsupported class (not enable or yet implemented) { - p_desc += p_desc[DESCRIPTOR_OFFSET_LENGTH]; // skip this interface, the rest will be skipped by the above loop + p_desc += p_desc[DESC_OFFSET_LEN]; // skip this interface, the rest will be skipped by the above loop } } } -- cgit v1.3.1 From 19b6bbfd14778c5a1fd13d2c0665dfbaa49c9425 Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 14 Jul 2018 23:28:07 +0700 Subject: add device cdc wanted char callback, cdc peek --- src/class/cdc/cdc_device.c | 53 +++++++++++++++++++++++++++++++++++----------- src/class/cdc/cdc_device.h | 3 +++ src/common/tusb_fifo.c | 10 ++++----- src/common/tusb_fifo.h | 2 +- 4 files changed, 50 insertions(+), 18 deletions(-) (limited to 'src/common') diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index d0c76d00f..04402c5bb 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -79,8 +79,10 @@ typedef struct //--------------------------------------------------------------------+ // INTERNAL OBJECT & FUNCTION DECLARATION //--------------------------------------------------------------------+ -CFG_TUSB_ATTR_USBRAM CFG_TUSB_MEM_ALIGN static uint8_t _tmp_rx_buf[64]; -CFG_TUSB_ATTR_USBRAM CFG_TUSB_MEM_ALIGN static uint8_t _tmp_tx_buf[64]; + +// TODO multiple interfaces +CFG_TUSB_ATTR_USBRAM CFG_TUSB_MEM_ALIGN static uint8_t _rx_buf[64]; +CFG_TUSB_ATTR_USBRAM CFG_TUSB_MEM_ALIGN static uint8_t _tx_buf[64]; static cdcd_interface_t _cdcd_itf[CFG_TUD_CDC]; @@ -105,7 +107,7 @@ void tud_cdc_n_get_line_coding (uint8_t itf, cdc_line_coding_t* coding) void tud_cdc_n_set_wanted_char (uint8_t itf, char wanted) { - + _cdcd_itf[itf].intact.wanted_char = wanted; } @@ -128,6 +130,12 @@ uint32_t tud_cdc_n_read(uint8_t itf, void* buffer, uint32_t bufsize) return tu_fifo_read_n(&_cdcd_itf[itf].intact.rx_ff, buffer, bufsize); } +char tud_cdc_n_peek(uint8_t itf, int pos) +{ + char ch; + return tu_fifo_peek_at(&_cdcd_itf[itf].intact.rx_ff, pos, &ch) ? ch : (-1); +} + //--------------------------------------------------------------------+ // WRITE API //--------------------------------------------------------------------+ @@ -147,11 +155,11 @@ bool tud_cdc_n_flush (uint8_t itf) uint8_t edpt = _cdcd_itf[itf].ep_in; VERIFY( !dcd_edpt_busy(TUD_RHPORT, edpt) ); // skip if previous transfer not complete - uint16_t count = tu_fifo_read_n(&_cdcd_itf[itf].intact.tx_ff, _tmp_tx_buf, sizeof(_tmp_tx_buf)); + uint16_t count = tu_fifo_read_n(&_cdcd_itf[itf].intact.tx_ff, _tx_buf, sizeof(_tx_buf)); VERIFY( tud_cdc_n_connected(itf) ); // fifo is empty if not connected - if ( count ) TU_ASSERT( dcd_edpt_xfer(TUD_RHPORT, edpt, _tmp_tx_buf, count) ); + if ( count ) TU_ASSERT( dcd_edpt_xfer(TUD_RHPORT, edpt, _tx_buf, count) ); return true; } @@ -166,6 +174,15 @@ void cdcd_init(void) for(uint8_t i=0; iep_out, _tmp_rx_buf, sizeof(_tmp_rx_buf)), TUSB_ERROR_DCD_EDPT_XFER); + TU_ASSERT( dcd_edpt_xfer(rhport, p_cdc->ep_out, _rx_buf, sizeof(_rx_buf)), TUSB_ERROR_DCD_EDPT_XFER); return TUSB_ERROR_NONE; } @@ -297,18 +314,30 @@ tusb_error_t cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, tusb_event_t event, u { // TODO Support multiple interfaces uint8_t const itf = 0; - cdcd_interface_t const * p_cdc = &_cdcd_itf[itf]; + cdcd_interface_t* p_cdc = &_cdcd_itf[itf]; // receive new data if ( ep_addr == p_cdc->ep_out ) { - tu_fifo_write_n(&_cdcd_itf[itf].intact.rx_ff, _tmp_rx_buf, xferred_bytes); + char const wanted = p_cdc->intact.wanted_char; + + for(uint32_t i=0; iintact.rx_ff, &_rx_buf[i]); + } + } - // preparing for next - TU_ASSERT( dcd_edpt_xfer(rhport, p_cdc->ep_out, _tmp_rx_buf, sizeof(_tmp_rx_buf)), TUSB_ERROR_DCD_EDPT_XFER ); + // invoke receive callback (if there is still data) + if (tud_cdc_rx_cb && tu_fifo_count(&p_cdc->intact.rx_ff) ) tud_cdc_rx_cb(itf); - // fire callback - if (tud_cdc_rx_cb) tud_cdc_rx_cb(itf); + // prepare for next + TU_ASSERT( dcd_edpt_xfer(rhport, p_cdc->ep_out, _rx_buf, sizeof(_rx_buf)), TUSB_ERROR_DCD_EDPT_XFER ); } // nothing to do with in and notif endpoint diff --git a/src/class/cdc/cdc_device.h b/src/class/cdc/cdc_device.h index 2ff822240..c815a42b6 100644 --- a/src/class/cdc/cdc_device.h +++ b/src/class/cdc/cdc_device.h @@ -64,6 +64,7 @@ void tud_cdc_n_set_wanted_char (uint8_t itf, char wanted); uint32_t tud_cdc_n_available (uint8_t itf); char tud_cdc_n_read_char (uint8_t itf); uint32_t tud_cdc_n_read (uint8_t itf, void* buffer, uint32_t bufsize); +char tud_cdc_n_peek (uint8_t itf, int pos); uint32_t tud_cdc_n_write_char (uint8_t itf, char ch); uint32_t tud_cdc_n_write (uint8_t itf, void const* buffer, uint32_t bufsize); @@ -80,6 +81,7 @@ static inline void tud_cdc_set_wanted_char (char wanted) static inline uint32_t tud_cdc_available (void) { return tud_cdc_n_available(0); } static inline char tud_cdc_read_char (void) { return tud_cdc_n_read_char(0); } static inline uint32_t tud_cdc_read (void* buffer, uint32_t bufsize) { return tud_cdc_n_read(0, buffer, bufsize); } +static inline char tud_cdc_peek (int pos) { return tud_cdc_n_peek(0, pos); } static inline uint32_t tud_cdc_write_char (char ch) { return tud_cdc_n_write_char(0, ch); } static inline uint32_t tud_cdc_write (void const* buffer, uint32_t bufsize) { return tud_cdc_n_write(0, buffer, bufsize); } @@ -89,6 +91,7 @@ static inline bool tud_cdc_flush (void) // APPLICATION CALLBACK API (WEAK is optional) //--------------------------------------------------------------------+ ATTR_WEAK void tud_cdc_rx_cb(uint8_t itf); +ATTR_WEAK void tud_cdc_rx_wanted_cb(uint8_t itf, char wanted_char); ATTR_WEAK void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts); ATTR_WEAK void tud_cdc_line_coding_cb(uint8_t itf, cdc_line_coding_t const* p_line_coding); diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index 03c0b63ab..09763bee0 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -166,7 +166,7 @@ uint16_t tu_fifo_read_n (tu_fifo_t* f, void * p_buffer, uint16_t count) @param[in] f Pointer to the FIFO buffer to manipulate - @param[in] position + @param[in] pos Position to read from in the FIFO buffer @param[in] p_buffer Pointer to the place holder for data read from the buffer @@ -174,13 +174,13 @@ uint16_t tu_fifo_read_n (tu_fifo_t* f, void * p_buffer, uint16_t count) @returns TRUE if the queue is not empty */ /******************************************************************************/ -bool tu_fifo_peek_at(tu_fifo_t* f, uint16_t position, void * p_buffer) +bool tu_fifo_peek_at(tu_fifo_t* f, uint16_t pos, void * p_buffer) { if ( !tu_fifo_initalized(f) ) return false; - if ( position >= f->count ) return false; + if ( pos >= f->count ) return false; - // rd_idx is position=0 - uint16_t index = (f->rd_idx + position) % f->depth; + // rd_idx is pos=0 + uint16_t index = (f->rd_idx + pos) % f->depth; memcpy(p_buffer, f->buffer + (index * f->item_size), f->item_size); diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index d87b32395..1ddf3bd94 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -123,7 +123,7 @@ uint16_t tu_fifo_write_n (tu_fifo_t* f, void const * p_data, uint16_t count); bool tu_fifo_read (tu_fifo_t* f, void * p_buffer); uint16_t tu_fifo_read_n (tu_fifo_t* f, void * p_buffer, uint16_t count); -bool tu_fifo_peek_at (tu_fifo_t* f, uint16_t position, void * p_buffer); +bool tu_fifo_peek_at (tu_fifo_t* f, uint16_t pos, void * p_buffer); static inline bool tu_fifo_peek(tu_fifo_t* f, void * p_buffer) { -- cgit v1.3.1 From abb37e98baa16ae9f99f9d7562e4ee166e8bc4de Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 14 Jul 2018 23:43:19 +0700 Subject: rename tud_cdc_flush() to tud_cdc_write_flush(), add tud_cdc_read_flush() --- examples/device/device_virtual_com/src/tusb_config.h | 2 +- examples/device/nrf52840/src/main.c | 2 +- examples/device/nrf52840/src/tusb_config.h | 2 +- examples/obsolete/device/src/tusb_config.h | 2 +- src/class/cdc/cdc_device.c | 7 ++++++- src/class/cdc/cdc_device.h | 5 +++-- src/common/tusb_verify.h | 1 + 7 files changed, 14 insertions(+), 7 deletions(-) (limited to 'src/common') diff --git a/examples/device/device_virtual_com/src/tusb_config.h b/examples/device/device_virtual_com/src/tusb_config.h index a69d2ecbb..511b81b78 100644 --- a/examples/device/device_virtual_com/src/tusb_config.h +++ b/examples/device/device_virtual_com/src/tusb_config.h @@ -90,7 +90,7 @@ // TX is sent automatically every Start of Frame event. -// If not enabled, application must call tud_cdc_flush() periodically +// If not enabled, application must call tud_cdc_write_flush() periodically #define CFG_TUD_CDC_FLUSH_ON_SOF 1 //--------------------------------------------------------------------+ diff --git a/examples/device/nrf52840/src/main.c b/examples/device/nrf52840/src/main.c index e6a6388bf..ec574738e 100644 --- a/examples/device/nrf52840/src/main.c +++ b/examples/device/nrf52840/src/main.c @@ -87,7 +87,7 @@ void virtual_com_task(void) uint32_t count = tud_cdc_read(buf, sizeof(buf)); tud_cdc_write(buf, count); - tud_cdc_flush(); + tud_cdc_write_flush(); } } diff --git a/examples/device/nrf52840/src/tusb_config.h b/examples/device/nrf52840/src/tusb_config.h index 258a5983d..62c788413 100644 --- a/examples/device/nrf52840/src/tusb_config.h +++ b/examples/device/nrf52840/src/tusb_config.h @@ -86,7 +86,7 @@ #define CFG_TUD_CDC_TX_BUFSIZE 64 // TX is sent automatically every Start of Frame event. -// If not enabled, application must call tud_cdc_flush() periodically +// If not enabled, application must call tud_cdc_write_flush() periodically #define CFG_TUD_CDC_FLUSH_ON_SOF 0 /*------------------------------------------------------------------*/ diff --git a/examples/obsolete/device/src/tusb_config.h b/examples/obsolete/device/src/tusb_config.h index 16003dd6d..8c8d32514 100644 --- a/examples/obsolete/device/src/tusb_config.h +++ b/examples/obsolete/device/src/tusb_config.h @@ -88,7 +88,7 @@ // TX is sent automatically in Start of Frame event. -// If not enabled, application must call tud_cdc_flush() periodically +// If not enabled, application must call tud_cdc_write_flush() periodically #define CFG_TUD_CDC_FLUSH_ON_SOF 1 diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index 04402c5bb..bcef47136 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -136,6 +136,11 @@ char tud_cdc_n_peek(uint8_t itf, int pos) return tu_fifo_peek_at(&_cdcd_itf[itf].intact.rx_ff, pos, &ch) ? ch : (-1); } +void tud_cdc_n_read_flush (uint8_t itf) +{ + tu_fifo_clear(&_cdcd_itf[itf].intact.rx_ff); +} + //--------------------------------------------------------------------+ // WRITE API //--------------------------------------------------------------------+ @@ -150,7 +155,7 @@ uint32_t tud_cdc_n_write(uint8_t itf, void const* buffer, uint32_t bufsize) return tu_fifo_write_n(&_cdcd_itf[itf].intact.tx_ff, buffer, bufsize); } -bool tud_cdc_n_flush (uint8_t itf) +bool tud_cdc_n_write_flush (uint8_t itf) { uint8_t edpt = _cdcd_itf[itf].ep_in; VERIFY( !dcd_edpt_busy(TUD_RHPORT, edpt) ); // skip if previous transfer not complete diff --git a/src/class/cdc/cdc_device.h b/src/class/cdc/cdc_device.h index c815a42b6..0a1b2ca8f 100644 --- a/src/class/cdc/cdc_device.h +++ b/src/class/cdc/cdc_device.h @@ -64,11 +64,12 @@ void tud_cdc_n_set_wanted_char (uint8_t itf, char wanted); uint32_t tud_cdc_n_available (uint8_t itf); char tud_cdc_n_read_char (uint8_t itf); uint32_t tud_cdc_n_read (uint8_t itf, void* buffer, uint32_t bufsize); +void tud_cdc_n_read_flush (uint8_t itf); char tud_cdc_n_peek (uint8_t itf, int pos); uint32_t tud_cdc_n_write_char (uint8_t itf, char ch); uint32_t tud_cdc_n_write (uint8_t itf, void const* buffer, uint32_t bufsize); -bool tud_cdc_n_flush (uint8_t itf); +bool tud_cdc_n_write_flush (uint8_t itf); //--------------------------------------------------------------------+ // APPLICATION API (Interface0) @@ -85,7 +86,7 @@ static inline char tud_cdc_peek (int pos) static inline uint32_t tud_cdc_write_char (char ch) { return tud_cdc_n_write_char(0, ch); } static inline uint32_t tud_cdc_write (void const* buffer, uint32_t bufsize) { return tud_cdc_n_write(0, buffer, bufsize); } -static inline bool tud_cdc_flush (void) { return tud_cdc_n_flush(0); } +static inline bool tud_cdc_write_flush (void) { return tud_cdc_n_write_flush(0); } //--------------------------------------------------------------------+ // APPLICATION CALLBACK API (WEAK is optional) diff --git a/src/common/tusb_verify.h b/src/common/tusb_verify.h index 0e1f3b934..95816a0e7 100644 --- a/src/common/tusb_verify.h +++ b/src/common/tusb_verify.h @@ -61,6 +61,7 @@ // VERIFY Helper //--------------------------------------------------------------------+ #if CFG_TUSB_DEBUG >= 1 + #include #define _MESS_ERR(_err) printf("%s: %d: failed, error = %s\n", __func__, __LINE__, tusb_strerr[_err]) #define _MESS_FAILED() printf("%s: %d: failed\n", __func__, __LINE__) #else -- cgit v1.3.1 From 3e209f9c20c9251e01af35da4d9e454fcc2f61dd Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 23 Jul 2018 17:46:07 +0700 Subject: enhance device hid - add CFG_TUD_HID_ASCII_TO_KEYCODE_LOOKUP - add tud_hid_keyboard_send_keycode(), tud_hid_keyboard_send_char(), tud_hid_keyboard_send_string() - add timeout_blocking_wait() --- examples/device/nrf52840/src/main.c | 27 ++++ examples/device/nrf52840/src/tusb_config.h | 7 + src/class/hid/hid.h | 211 +++++++++++++++------------- src/class/hid/hid_device.c | 216 +++++++++++++++++++++++++++-- src/class/hid/hid_device.h | 48 +++---- src/common/timeout_timer.h | 9 ++ 6 files changed, 386 insertions(+), 132 deletions(-) (limited to 'src/common') diff --git a/examples/device/nrf52840/src/main.c b/examples/device/nrf52840/src/main.c index 00937d7d2..1993109b4 100644 --- a/examples/device/nrf52840/src/main.c +++ b/examples/device/nrf52840/src/main.c @@ -76,6 +76,9 @@ int main(void) return 0; } +//--------------------------------------------------------------------+ +// USB CDC +//--------------------------------------------------------------------+ void virtual_com_task(void) { // connected and there are data available @@ -91,6 +94,30 @@ void virtual_com_task(void) } } +//--------------------------------------------------------------------+ +// USB CDC +//--------------------------------------------------------------------+ +void usb_hid_task(void) +{ + if ( tud_mounted() ) + { + if ( !tud_hid_keyboard_busy() ) + { + static bool toggle = false; // send either A or B + + tud_hid_keyboard_send_char( toggle ? 'A' : 'B' ); + toggle = !toggle; + } + + if ( !tud_hid_mouse_busy() ) + { + + } + + } +} + + //--------------------------------------------------------------------+ // tinyusb callbacks diff --git a/examples/device/nrf52840/src/tusb_config.h b/examples/device/nrf52840/src/tusb_config.h index da7dc793b..457dceea7 100644 --- a/examples/device/nrf52840/src/tusb_config.h +++ b/examples/device/nrf52840/src/tusb_config.h @@ -126,6 +126,13 @@ */ #define CFG_TUD_HID_BOOT_PROTOCOL 1 +/* Use the HID_ASCII_TO_KEYCODE lookup if CFG_TUD_HID_KEYBOARD is enabled. + * This will occupies 256 bytes of ROM. It will also enable the use of 2 extra APIs + * - tud_hid_keyboard_send_char() + * - tud_hid_keyboard_send_string() + */ +#define CFG_TUD_HID_ASCII_TO_KEYCODE_LOOKUP 1 + //-------------------------------------------------------------------- // USB RAM PLACEMENT //-------------------------------------------------------------------- diff --git a/src/class/hid/hid.h b/src/class/hid/hid.h index a12a13800..c898b09d4 100644 --- a/src/class/hid/hid.h +++ b/src/class/hid/hid.h @@ -217,101 +217,122 @@ typedef enum /// @} -#define HID_KEYCODE_TABLE(ENTRY) \ - ENTRY( 0x04, 'a' , 'A' )\ - ENTRY( 0x05, 'b' , 'B' )\ - ENTRY( 0x06, 'c' , 'C' )\ - ENTRY( 0x07, 'd' , 'D' )\ - ENTRY( 0x08, 'e' , 'E' )\ - ENTRY( 0x09, 'f' , 'F' )\ - ENTRY( 0x0a, 'g' , 'G' )\ - ENTRY( 0x0b, 'h' , 'H' )\ - ENTRY( 0x0c, 'i' , 'I' )\ - ENTRY( 0x0d, 'j' , 'J' )\ - ENTRY( 0x0e, 'k' , 'K' )\ - ENTRY( 0x0f, 'l' , 'L' )\ - ENTRY( 0x10, 'm' , 'M' )\ - ENTRY( 0x11, 'n' , 'N' )\ - ENTRY( 0x12, 'o' , 'O' )\ - ENTRY( 0x13, 'p' , 'P' )\ - ENTRY( 0x14, 'q' , 'Q' )\ - ENTRY( 0x15, 'r' , 'R' )\ - ENTRY( 0x16, 's' , 'S' )\ - ENTRY( 0x17, 't' , 'T' )\ - ENTRY( 0x18, 'u' , 'U' )\ - ENTRY( 0x19, 'v' , 'V' )\ - ENTRY( 0x1a, 'w' , 'W' )\ - ENTRY( 0x1b, 'x' , 'X' )\ - ENTRY( 0x1c, 'y' , 'Y' )\ - ENTRY( 0x1d, 'z' , 'Z' )\ - \ - ENTRY( 0x1e, '1' , '!' )\ - ENTRY( 0x1f, '2' , '@' )\ - ENTRY( 0x20, '3' , '#' )\ - ENTRY( 0x21, '4' , '$' )\ - ENTRY( 0x22, '5' , '%' )\ - ENTRY( 0x23, '6' , '^' )\ - ENTRY( 0x24, '7' , '&' )\ - ENTRY( 0x25, '8' , '*' )\ - ENTRY( 0x26, '9' , '(' )\ - ENTRY( 0x27, '0' , ')' )\ - \ - ENTRY( 0x28, '\r' , '\r' )\ - ENTRY( 0x29, '\x1b', '\x1b' )\ - ENTRY( 0x2a, '\b' , '\b' )\ - ENTRY( 0x2b, '\t' , '\t' )\ - ENTRY( 0x2c, ' ' , ' ' )\ - ENTRY( 0x2d, '-' , '_' )\ - ENTRY( 0x2e, '=' , '+' )\ - ENTRY( 0x2f, '[' , '{' )\ - ENTRY( 0x30, ']' , '}' )\ - ENTRY( 0x31, '\\' , '|' )\ - ENTRY( 0x32, '#' , '~' ) /* TODO non-US keyboard */ \ - ENTRY( 0x33, ';' , ':' )\ - ENTRY( 0x34, '\'' , '\"' )\ - ENTRY( 0x35, 0 , 0 )\ - ENTRY( 0x36, ',' , '<' )\ - ENTRY( 0x37, '.' , '>' )\ - ENTRY( 0x38, '/' , '?' )\ - ENTRY( 0x39, 0 , 0 ) /* TODO CapsLock, non-locking key implementation*/ \ - \ - ENTRY( 0x54, '/' , '/' )\ - ENTRY( 0x55, '*' , '*' )\ - ENTRY( 0x56, '-' , '-' )\ - ENTRY( 0x57, '+' , '+' )\ - ENTRY( 0x58, '\r' , '\r' )\ - ENTRY( 0x59, '1' , 0 ) /* numpad1 & end */ \ - ENTRY( 0x5a, '2' , 0 )\ - ENTRY( 0x5b, '3' , 0 )\ - ENTRY( 0x5c, '4' , 0 )\ - ENTRY( 0x5d, '5' , '5' )\ - ENTRY( 0x5e, '6' , 0 )\ - ENTRY( 0x5f, '7' , 0 )\ - ENTRY( 0x60, '8' , 0 )\ - ENTRY( 0x61, '9' , 0 )\ - ENTRY( 0x62, '0' , 0 )\ - ENTRY( 0x63, '0' , 0 )\ - ENTRY( 0x67, '=' , '=' )\ - - - -// TODO HID complete keycode table - -//enum -//{ -// KEYBOARD_KEYCODE_A = 0x04, -// KEYBOARD_KEYCODE_Z = 0x1d, -// -// KEYBOARD_KEYCODE_1 = 0x1e, -// KEYBOARD_KEYCODE_0 = 0x27, -// -// KEYBOARD_KEYCODE_ENTER = 0x28, -// KEYBOARD_KEYCODE_ESCAPE = 0x29, -// KEYBOARD_KEYCODE_BACKSPACE = 0x2a, -// KEYBOARD_KEYCODE_TAB = 0x2b, -// KEYBOARD_KEYCODE_SPACEBAR = 0x2c, -// -//}; +//--------------------------------------------------------------------+ +// HID KEYCODE +//--------------------------------------------------------------------+ +#define HID_KEY_NONE 0x00 +#define HID_KEY_A 0x04 +#define HID_KEY_B 0x05 +#define HID_KEY_C 0x06 +#define HID_KEY_D 0x07 +#define HID_KEY_E 0x08 +#define HID_KEY_F 0x09 +#define HID_KEY_G 0x0A +#define HID_KEY_H 0x0B +#define HID_KEY_I 0x0C +#define HID_KEY_J 0x0D +#define HID_KEY_K 0x0E +#define HID_KEY_L 0x0F +#define HID_KEY_M 0x10 +#define HID_KEY_N 0x11 +#define HID_KEY_O 0x12 +#define HID_KEY_P 0x13 +#define HID_KEY_Q 0x14 +#define HID_KEY_R 0x15 +#define HID_KEY_S 0x16 +#define HID_KEY_T 0x17 +#define HID_KEY_U 0x18 +#define HID_KEY_V 0x19 +#define HID_KEY_W 0x1A +#define HID_KEY_X 0x1B +#define HID_KEY_Y 0x1C +#define HID_KEY_Z 0x1D +#define HID_KEY_1 0x1E +#define HID_KEY_2 0x1F +#define HID_KEY_3 0x20 +#define HID_KEY_4 0x21 +#define HID_KEY_5 0x22 +#define HID_KEY_6 0x23 +#define HID_KEY_7 0x24 +#define HID_KEY_8 0x25 +#define HID_KEY_9 0x26 +#define HID_KEY_0 0x27 +#define HID_KEY_RETURN 0x28 +#define HID_KEY_ESCAPE 0x29 +#define HID_KEY_BACKSPACE 0x2A +#define HID_KEY_TAB 0x2B +#define HID_KEY_SPACE 0x2C +#define HID_KEY_MINUS 0x2D +#define HID_KEY_EQUAL 0x2E +#define HID_KEY_BRACKET_LEFT 0x2F +#define HID_KEY_BRACKET_RIGHT 0x30 +#define HID_KEY_BACKSLASH 0x31 +#define HID_KEY_EUROPE_1 0x32 +#define HID_KEY_SEMICOLON 0x33 +#define HID_KEY_APOSTROPHE 0x34 +#define HID_KEY_GRAVE 0x35 +#define HID_KEY_COMMA 0x36 +#define HID_KEY_PERIOD 0x37 +#define HID_KEY_SLASH 0x38 +#define HID_KEY_CAPS_LOCK 0x39 +#define HID_KEY_F1 0x3A +#define HID_KEY_F2 0x3B +#define HID_KEY_F3 0x3C +#define HID_KEY_F4 0x3D +#define HID_KEY_F5 0x3E +#define HID_KEY_F6 0x3F +#define HID_KEY_F7 0x40 +#define HID_KEY_F8 0x41 +#define HID_KEY_F9 0x42 +#define HID_KEY_F10 0x43 +#define HID_KEY_F11 0x44 +#define HID_KEY_F12 0x45 +#define HID_KEY_PRINT_SCREEN 0x46 +#define HID_KEY_SCROLL_LOCK 0x47 +#define HID_KEY_PAUSE 0x48 +#define HID_KEY_INSERT 0x49 +#define HID_KEY_HOME 0x4A +#define HID_KEY_PAGE_UP 0x4B +#define HID_KEY_DELETE 0x4C +#define HID_KEY_END 0x4D +#define HID_KEY_PAGE_DOWN 0x4E +#define HID_KEY_ARROW_RIGHT 0x4F +#define HID_KEY_ARROW_LEFT 0x50 +#define HID_KEY_ARROW_DOWN 0x51 +#define HID_KEY_ARROW_UP 0x52 +#define HID_KEY_NUM_LOCK 0x53 +#define HID_KEY_KEYPAD_DIVIDE 0x54 +#define HID_KEY_KEYPAD_MULTIPLY 0x55 +#define HID_KEY_KEYPAD_SUBTRACT 0x56 +#define HID_KEY_KEYPAD_ADD 0x57 +#define HID_KEY_KEYPAD_ENTER 0x58 +#define HID_KEY_KEYPAD_1 0x59 +#define HID_KEY_KEYPAD_2 0x5A +#define HID_KEY_KEYPAD_3 0x5B +#define HID_KEY_KEYPAD_4 0x5C +#define HID_KEY_KEYPAD_5 0x5D +#define HID_KEY_KEYPAD_6 0x5E +#define HID_KEY_KEYPAD_7 0x5F +#define HID_KEY_KEYPAD_8 0x60 +#define HID_KEY_KEYPAD_9 0x61 +#define HID_KEY_KEYPAD_0 0x62 +#define HID_KEY_KEYPAD_DECIMAL 0x63 +#define HID_KEY_EUROPE_2 0x64 +#define HID_KEY_APPLICATION 0x65 +#define HID_KEY_POWER 0x66 +#define HID_KEY_KEYPAD_EQUAL 0x67 +#define HID_KEY_F13 0x68 +#define HID_KEY_F14 0x69 +#define HID_KEY_F15 0x6A +#define HID_KEY_CONTROL_LEFT 0xE0 +#define HID_KEY_SHIFT_LEFT 0xE1 +#define HID_KEY_ALT_LEFT 0xE2 +#define HID_KEY_GUI_LEFT 0xE3 +#define HID_KEY_CONTROL_RIGHT 0xE4 +#define HID_KEY_SHIFT_RIGHT 0xE5 +#define HID_KEY_ALT_RIGHT 0xE6 +#define HID_KEY_GUI_RIGHT 0xE7 + //--------------------------------------------------------------------+ // REPORT DESCRIPTOR diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index 7b2c1da2d..f2d89250c 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -45,6 +45,7 @@ // INCLUDE //--------------------------------------------------------------------+ #include "common/tusb_common.h" +#include "common/timeout_timer.h" #include "hid_device.h" #include "device/usbd_pvt.h" @@ -91,16 +92,71 @@ bool tud_hid_keyboard_busy(void) return dcd_edpt_busy(TUD_OPT_RHPORT, _kbd_itf.ep_in); } -tusb_error_t tud_hid_keyboard_send(hid_keyboard_report_t const *p_report) +bool tud_hid_keyboard_send_report(hid_keyboard_report_t const *p_report) { - VERIFY(tud_mounted(), TUSB_ERROR_USBD_DEVICE_NOT_CONFIGURED); + VERIFY( tud_mounted() && !tud_hid_keyboard_busy() ); - hidd_interface_t * p_kbd = &_kbd_itf; + hidd_interface_t * p_hid = &_kbd_itf; - TU_ASSERT( dcd_edpt_xfer(TUD_OPT_RHPORT, p_kbd->ep_in, (void*) p_report, sizeof(hid_keyboard_report_t)), TUSB_ERROR_DCD_EDPT_XFER ) ; + if ( p_report ) + { + memcpy(p_hid->report_buf, p_report, sizeof(hid_keyboard_report_t)); + }else + { + // empty report + arrclr_(p_hid->report_buf); + } - return TUSB_ERROR_NONE; + return dcd_edpt_xfer(TUD_OPT_RHPORT, p_hid->ep_in, p_hid->report_buf, sizeof(hid_keyboard_report_t)); +} + +bool tud_hid_keyboard_send_keycode(uint8_t modifier, uint8_t keycode[6]) +{ + hid_keyboard_report_t report = { .modifier = modifier }; + memcpy(report.keycode, keycode, 6); + + return tud_hid_keyboard_send_report(&report); } + +#if CFG_TUD_HID_ASCII_TO_KEYCODE_LOOKUP + +bool tud_hid_keyboard_send_char(char ch) +{ + hid_keyboard_report_t report; + varclr_(&report); + + report.modifier = ( HID_ASCII_TO_KEYCODE[(uint8_t)ch].shift ) ? KEYBOARD_MODIFIER_LEFTSHIFT : 0; + report.keycode[0] = HID_ASCII_TO_KEYCODE[(uint8_t)ch].keycode; + + return tud_hid_keyboard_send_report(&report); +} + +bool tud_hid_keyboard_send_string(const char* str, uint32_t interval_ms) +{ + // Send each key in string + char ch; + while( (ch = *str++) != 0 ) + { + char lookahead = *str; + + tud_hid_keyboard_send_char(ch); + + // Blocking delay + timeout_blocking_wait(interval_ms); + + /* Only need to empty report if the next character is NULL or the same with + * the current one, else no need to send */ + if ( lookahead == ch || lookahead == 0 ) + { + tud_hid_keyboard_send_report(NULL); + timeout_blocking_wait(interval_ms); + } + } + +} + +#endif // CFG_TUD_HID_ASCII_TO_KEYCODE_LOOKUP + #endif //--------------------------------------------------------------------+ @@ -112,15 +168,14 @@ bool tud_hid_mouse_is_busy(void) return dcd_edpt_busy(TUD_OPT_RHPORT, _mse_itf.ep_in); } -tusb_error_t tud_hid_mouse_send(hid_mouse_report_t const *p_report) +bool tud_hid_mouse_send(hid_mouse_report_t const *p_report) { - VERIFY(tud_mounted(), TUSB_ERROR_USBD_DEVICE_NOT_CONFIGURED); - - hidd_interface_t * p_mouse = &_mse_itf; + VERIFY( tud_mounted() && !tud_hid_mouse_is_busy() ); - TU_ASSERT( dcd_edpt_xfer(TUD_OPT_RHPORT, p_mouse->ep_in, (void*) p_report, sizeof(hid_mouse_report_t)), TUSB_ERROR_DCD_EDPT_XFER ) ; + hidd_interface_t * p_hid = &_mse_itf; + memcpy(p_hid->report_buf, p_report, sizeof(hid_mouse_report_t)); - return TUSB_ERROR_NONE; + return dcd_edpt_xfer(TUD_OPT_RHPORT, p_hid->ep_in, p_hid->report_buf, sizeof(hid_mouse_report_t)); } #endif @@ -327,4 +382,143 @@ tusb_error_t hidd_xfer_cb(uint8_t rhport, uint8_t edpt_addr, tusb_event_t event, return TUSB_ERROR_NONE; } + +/*------------------------------------------------------------------*/ +/* Ascii to Keycode + *------------------------------------------------------------------*/ +const hid_ascii_to_keycode_entry_t HID_ASCII_TO_KEYCODE[128] = +{ + {0, 0 }, // 0x00 Null + {0, 0 }, // 0x01 + {0, 0 }, // 0x02 + {0, 0 }, // 0x03 + {0, 0 }, // 0x04 + {0, 0 }, // 0x05 + {0, 0 }, // 0x06 + {0, 0 }, // 0x07 + {0, HID_KEY_BACKSPACE }, // 0x08 Backspace + {0, HID_KEY_TAB }, // 0x09 Horizontal Tab + {0, HID_KEY_RETURN }, // 0x0A Line Feed + {0, 0 }, // 0x0B + {0, 0 }, // 0x0C + {0, HID_KEY_RETURN }, // 0x0D Carriage return + {0, 0 }, // 0x0E + {0, 0 }, // 0x0F + {0, 0 }, // 0x10 + {0, 0 }, // 0x11 + {0, 0 }, // 0x12 + {0, 0 }, // 0x13 + {0, 0 }, // 0x14 + {0, 0 }, // 0x15 + {0, 0 }, // 0x16 + {0, 0 }, // 0x17 + {0, 0 }, // 0x18 + {0, 0 }, // 0x19 + {0, 0 }, // 0x1A + {0, HID_KEY_ESCAPE }, // 0x1B Escape + {0, 0 }, // 0x1C + {0, 0 }, // 0x1D + {0, 0 }, // 0x1E + {0, 0 }, // 0x1F + + {0, HID_KEY_SPACE }, // 0x20 + {1, HID_KEY_1 }, // 0x21 ! + {1, HID_KEY_APOSTROPHE }, // 0x22 " + {1, HID_KEY_3 }, // 0x23 # + {1, HID_KEY_4 }, // 0x24 $ + {1, HID_KEY_5 }, // 0x25 % + {1, HID_KEY_7 }, // 0x26 & + {0, HID_KEY_APOSTROPHE }, // 0x27 ' + {1, HID_KEY_9 }, // 0x28 ( + {1, HID_KEY_0 }, // 0x29 ) + {1, HID_KEY_8 }, // 0x2A * + {1, HID_KEY_EQUAL }, // 0x2B + + {0, HID_KEY_COMMA }, // 0x2C , + {0, HID_KEY_MINUS }, // 0x2D - + {0, HID_KEY_PERIOD }, // 0x2E . + {0, HID_KEY_SLASH }, // 0x2F / + {0, HID_KEY_0 }, // 0x30 0 + {0, HID_KEY_1 }, // 0x31 1 + {0, HID_KEY_2 }, // 0x32 2 + {0, HID_KEY_3 }, // 0x33 3 + {0, HID_KEY_4 }, // 0x34 4 + {0, HID_KEY_5 }, // 0x35 5 + {0, HID_KEY_6 }, // 0x36 6 + {0, HID_KEY_7 }, // 0x37 7 + {0, HID_KEY_8 }, // 0x38 8 + {0, HID_KEY_9 }, // 0x39 9 + {1, HID_KEY_SEMICOLON }, // 0x3A : + {0, HID_KEY_SEMICOLON }, // 0x3B ; + {1, HID_KEY_COMMA }, // 0x3C < + {0, HID_KEY_EQUAL }, // 0x3D = + {1, HID_KEY_PERIOD }, // 0x3E > + {1, HID_KEY_SLASH }, // 0x3F ? + + {1, HID_KEY_2 }, // 0x40 @ + {1, HID_KEY_A }, // 0x41 A + {1, HID_KEY_B }, // 0x42 B + {1, HID_KEY_C }, // 0x43 C + {1, HID_KEY_D }, // 0x44 D + {1, HID_KEY_E }, // 0x45 E + {1, HID_KEY_F }, // 0x46 F + {1, HID_KEY_G }, // 0x47 G + {1, HID_KEY_H }, // 0x48 H + {1, HID_KEY_I }, // 0x49 I + {1, HID_KEY_J }, // 0x4A J + {1, HID_KEY_K }, // 0x4B K + {1, HID_KEY_L }, // 0x4C L + {1, HID_KEY_M }, // 0x4D M + {1, HID_KEY_N }, // 0x4E N + {1, HID_KEY_O }, // 0x4F O + {1, HID_KEY_P }, // 0x50 P + {1, HID_KEY_Q }, // 0x51 Q + {1, HID_KEY_R }, // 0x52 R + {1, HID_KEY_S }, // 0x53 S + {1, HID_KEY_T }, // 0x55 T + {1, HID_KEY_U }, // 0x55 U + {1, HID_KEY_V }, // 0x56 V + {1, HID_KEY_W }, // 0x57 W + {1, HID_KEY_X }, // 0x58 X + {1, HID_KEY_Y }, // 0x59 Y + {1, HID_KEY_Z }, // 0x5A Z + {0, HID_KEY_BRACKET_LEFT }, // 0x5B [ + {0, HID_KEY_BACKSLASH }, // 0x5C '\' + {0, HID_KEY_BRACKET_RIGHT }, // 0x5D ] + {1, HID_KEY_6 }, // 0x5E ^ + {1, HID_KEY_MINUS }, // 0x5F _ + + {0, HID_KEY_GRAVE }, // 0x60 ` + {0, HID_KEY_A }, // 0x61 a + {0, HID_KEY_B }, // 0x62 b + {0, HID_KEY_C }, // 0x63 c + {0, HID_KEY_D }, // 0x66 d + {0, HID_KEY_E }, // 0x65 e + {0, HID_KEY_F }, // 0x66 f + {0, HID_KEY_G }, // 0x67 g + {0, HID_KEY_H }, // 0x68 h + {0, HID_KEY_I }, // 0x69 i + {0, HID_KEY_J }, // 0x6A j + {0, HID_KEY_K }, // 0x6B k + {0, HID_KEY_L }, // 0x6C l + {0, HID_KEY_M }, // 0x6D m + {0, HID_KEY_N }, // 0x6E n + {0, HID_KEY_O }, // 0x6F o + {0, HID_KEY_P }, // 0x70 p + {0, HID_KEY_Q }, // 0x71 q + {0, HID_KEY_R }, // 0x72 r + {0, HID_KEY_S }, // 0x73 s + {0, HID_KEY_T }, // 0x75 t + {0, HID_KEY_U }, // 0x75 u + {0, HID_KEY_V }, // 0x76 v + {0, HID_KEY_W }, // 0x77 w + {0, HID_KEY_X }, // 0x78 x + {0, HID_KEY_Y }, // 0x79 y + {0, HID_KEY_Z }, // 0x7A z + {1, HID_KEY_BRACKET_LEFT }, // 0x7B { + {1, HID_KEY_BACKSLASH }, // 0x7C | + {1, HID_KEY_BRACKET_RIGHT }, // 0x7D } + {1, HID_KEY_GRAVE }, // 0x7E ~ + {0, HID_KEY_DELETE } // 0x7F Delete +}; + #endif diff --git a/src/class/hid/hid_device.h b/src/class/hid/hid_device.h index a2238473d..21561041a 100644 --- a/src/class/hid/hid_device.h +++ b/src/class/hid/hid_device.h @@ -63,22 +63,26 @@ */ bool tud_hid_keyboard_busy(void); -/** \brief Submit USB transfer - * \param[in] rhport USB Controller ID - * \param[in,out] p_report address that is used to store data from device. Must be accessible by usb controller (see \ref CFG_TUSB_ATTR_USBRAM) - * \returns \ref tusb_error_t type to indicate success or error condition. - * \retval TUSB_ERROR_NONE on success - * \retval TUSB_ERROR_INTERFACE_IS_BUSY if the interface is already transferring data with device - * \retval TUSB_ERROR_DEVICE_NOT_READY if device is not yet configured (by SET CONFIGURED request) - * \retval TUSB_ERROR_INVALID_PARA if input parameters are not correct - * \note This function is non-blocking and returns immediately. Data will be transferred when USB Host work with this interface. - * The result of usb transfer will be reported by the interface's callback function +/** \brief Send a keyboard report + * \param[in,out] p_report Report data, if NULL, an empty report (all zeroes) is used + * \returns true on success, false otherwise (not mounted or busy) */ -tusb_error_t tud_hid_keyboard_send(hid_keyboard_report_t const *p_report); +bool tud_hid_keyboard_send_report(hid_keyboard_report_t const *p_report); -//--------------------------------------------------------------------+ -// APPLICATION CALLBACK API -//--------------------------------------------------------------------+ +bool tud_hid_keyboard_send_keycode(uint8_t modifier, uint8_t keycode[6]); + +#if CFG_TUD_HID_ASCII_TO_KEYCODE_LOOKUP +bool tud_hid_keyboard_send_char(char ch); +bool tud_hid_keyboard_send_string(const char* str, uint32_t interval_ms); + +typedef struct{ + uint8_t shift; + uint8_t keycode; +}hid_ascii_to_keycode_entry_t; +extern const hid_ascii_to_keycode_entry_t HID_ASCII_TO_KEYCODE[128]; +#endif + +/*------------- Callbacks -------------*/ /** \brief Callback function that is invoked when USB host request \ref HID_REQUEST_CONTROL_GET_REPORT * via control endpoint. @@ -120,23 +124,15 @@ ATTR_WEAK void tud_hid_keyboard_set_report_cb(hid_report_type_t report_type, uin * \retval false if the interface is not busy meaning the stack successfully transferred data from/to host * \note This function is primarily used for polling/waiting result after \ref tusbd_hid_mouse_send. */ -bool tud_hid_mouse_is_busy(void); +bool tud_hid_mouse_busy(void); /** \brief Perform transfer queuing * \param[in,out] p_report address that is used to store data from device. Must be accessible by usb controller (see \ref CFG_TUSB_ATTR_USBRAM) - * \returns \ref tusb_error_t type to indicate success or error condition. - * \retval TUSB_ERROR_NONE on success - * \retval TUSB_ERROR_INTERFACE_IS_BUSY if the interface is already transferring data with device - * \retval TUSB_ERROR_DEVICE_NOT_READY if device is not yet configured (by SET CONFIGURED request) - * \retval TUSB_ERROR_INVALID_PARA if input parameters are not correct - * \note This function is non-blocking and returns immediately. Data will be transferred when USB Host work with this interface. - * The result of usb transfer will be reported by the interface's callback function + * \returns true on success, false otherwise (not mounted or busy) */ -tusb_error_t tud_hid_mouse_send(hid_mouse_report_t const *p_report); +bool tud_hid_mouse_send(hid_mouse_report_t const *p_report); -//--------------------------------------------------------------------+ -// APPLICATION CALLBACK API -//--------------------------------------------------------------------+ +/*------------- Callbacks -------------*/ /** \brief Callback function that is invoked when USB host request \ref HID_REQUEST_CONTROL_GET_REPORT * via control endpoint. diff --git a/src/common/timeout_timer.h b/src/common/timeout_timer.h index aafc8cce2..5c62c6904 100644 --- a/src/common/timeout_timer.h +++ b/src/common/timeout_timer.h @@ -67,6 +67,15 @@ static inline bool timeout_expired(timeout_timer_t* tt) return ( tusb_hal_millis() - tt->start ) >= tt->interval; } +static inline void timeout_blocking_wait(uint32_t msec) +{ + timeout_timer_t tt; + timeout_set(&tt, msec); + + // blocking delay + while ( !timeout_expired(&tt) ) { } +} + #ifdef __cplusplus } #endif -- cgit v1.3.1 From 361928f42983bed4d10443668d8eb3db69ade80f Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 23 Jul 2018 22:32:21 +0700 Subject: rename timeout_timer.h to tusb_timeout.h --- src/class/hid/hid_device.c | 2 +- src/common/timeout_timer.h | 85 ---------------------- src/common/tusb_timeout.h | 85 ++++++++++++++++++++++ src/host/ehci/ehci.c | 2 +- src/host/ohci/ohci.c | 2 +- .../nxp/lpc11xx_lpc13xx/dcd_lpc_11uxx_13uxx.c | 2 +- src/portable/nxp/lpc43xx_lpc18xx/dcd_lpc43xx.c | 2 +- 7 files changed, 90 insertions(+), 90 deletions(-) delete mode 100644 src/common/timeout_timer.h create mode 100644 src/common/tusb_timeout.h (limited to 'src/common') diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index 325485425..4ce927725 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -45,7 +45,7 @@ // INCLUDE //--------------------------------------------------------------------+ #include "common/tusb_common.h" -#include "common/timeout_timer.h" +#include "common/tusb_timeout.h" #include "hid_device.h" #include "device/usbd_pvt.h" diff --git a/src/common/timeout_timer.h b/src/common/timeout_timer.h deleted file mode 100644 index 5c62c6904..000000000 --- a/src/common/timeout_timer.h +++ /dev/null @@ -1,85 +0,0 @@ -/**************************************************************************/ -/*! - @file timeout_timer.h - @author hathach (tinyusb.org) - - @section LICENSE - - Software License Agreement (BSD License) - - Copyright (c) 2013, hathach (tinyusb.org) - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - 3. Neither the name of the copyright holders nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY - EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - INCLUDING NEGLIGENCE OR OTHERWISE ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - This file is part of the tinyusb stack. -*/ -/**************************************************************************/ - -/** \ingroup Group_Common Common Files - * \defgroup Group_TimeoutTimer timeout timer - * @{ */ - - -#ifndef _TUSB_TIMEOUT_TTIMER_H_ -#define _TUSB_TIMEOUT_TTIMER_H_ - -#include "tusb_compiler.h" -#include "tusb_hal.h" - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct { - uint32_t start; - uint32_t interval; -}timeout_timer_t; - -static inline void timeout_set(timeout_timer_t* tt, uint32_t msec) -{ - tt->interval = msec; - tt->start = tusb_hal_millis(); -} - -static inline bool timeout_expired(timeout_timer_t* tt) -{ - return ( tusb_hal_millis() - tt->start ) >= tt->interval; -} - -static inline void timeout_blocking_wait(uint32_t msec) -{ - timeout_timer_t tt; - timeout_set(&tt, msec); - - // blocking delay - while ( !timeout_expired(&tt) ) { } -} - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_TIMEOUT_TTIMER_H_ */ - -/** @} */ diff --git a/src/common/tusb_timeout.h b/src/common/tusb_timeout.h new file mode 100644 index 000000000..400434708 --- /dev/null +++ b/src/common/tusb_timeout.h @@ -0,0 +1,85 @@ +/**************************************************************************/ +/*! + @file tusb_timeout.h + @author hathach (tinyusb.org) + + @section LICENSE + + Software License Agreement (BSD License) + + Copyright (c) 2013, hathach (tinyusb.org) + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holders nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + INCLUDING NEGLIGENCE OR OTHERWISE ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + This file is part of the tinyusb stack. +*/ +/**************************************************************************/ + +/** \ingroup Group_Common Common Files + * \defgroup Group_TimeoutTimer timeout timer + * @{ */ + + +#ifndef _TUSB_TIMEOUT_H_ +#define _TUSB_TIMEOUT_H_ + +#include "tusb_compiler.h" +#include "tusb_hal.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + uint32_t start; + uint32_t interval; +}timeout_timer_t; + +static inline void timeout_set(timeout_timer_t* tt, uint32_t msec) +{ + tt->interval = msec; + tt->start = tusb_hal_millis(); +} + +static inline bool timeout_expired(timeout_timer_t* tt) +{ + return ( tusb_hal_millis() - tt->start ) >= tt->interval; +} + +static inline void timeout_blocking_wait(uint32_t msec) +{ + timeout_timer_t tt; + timeout_set(&tt, msec); + + // blocking delay + while ( !timeout_expired(&tt) ) { } +} + +#ifdef __cplusplus + } +#endif + +#endif /* _TUSB_TIMEOUT_H_ */ + +/** @} */ diff --git a/src/host/ehci/ehci.c b/src/host/ehci/ehci.c index c9cd39378..9e326ec53 100644 --- a/src/host/ehci/ehci.c +++ b/src/host/ehci/ehci.c @@ -44,7 +44,7 @@ //--------------------------------------------------------------------+ #include "hal/hal.h" #include "osal/osal.h" -#include "common/timeout_timer.h" +#include "common/tusb_timeout.h" #include "../hcd.h" #include "../usbh_hcd.h" diff --git a/src/host/ohci/ohci.c b/src/host/ohci/ohci.c index 5788aac94..73e9d887e 100644 --- a/src/host/ohci/ohci.c +++ b/src/host/ohci/ohci.c @@ -44,7 +44,7 @@ //--------------------------------------------------------------------+ #include "hal/hal.h" #include "osal/osal.h" -#include "common/timeout_timer.h" +#include "common/tusb_timeout.h" #include "../hcd.h" #include "../usbh_hcd.h" diff --git a/src/portable/nxp/lpc11xx_lpc13xx/dcd_lpc_11uxx_13uxx.c b/src/portable/nxp/lpc11xx_lpc13xx/dcd_lpc_11uxx_13uxx.c index f0472f41d..0bb79090e 100644 --- a/src/portable/nxp/lpc11xx_lpc13xx/dcd_lpc_11uxx_13uxx.c +++ b/src/portable/nxp/lpc11xx_lpc13xx/dcd_lpc_11uxx_13uxx.c @@ -51,7 +51,7 @@ #include "common/tusb_common.h" #include "hal/hal.h" #include "osal/osal.h" -#include "common/timeout_timer.h" +#include "common/tusb_timeout.h" #include "device/dcd.h" #include "usbd_dcd.h" diff --git a/src/portable/nxp/lpc43xx_lpc18xx/dcd_lpc43xx.c b/src/portable/nxp/lpc43xx_lpc18xx/dcd_lpc43xx.c index a08e20a3f..6c076baa8 100644 --- a/src/portable/nxp/lpc43xx_lpc18xx/dcd_lpc43xx.c +++ b/src/portable/nxp/lpc43xx_lpc18xx/dcd_lpc43xx.c @@ -46,7 +46,7 @@ #include "common/tusb_common.h" #include "tusb_hal.h" #include "osal/osal.h" -#include "common/timeout_timer.h" +#include "common/tusb_timeout.h" #include "device/dcd.h" #include "dcd_lpc43xx.h" -- cgit v1.3.1 From 51903a60c51bd1006bec9266dbe1bfb35e282675 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 23 Jul 2018 22:36:29 +0700 Subject: rename timeout_ API to tu_timeout API --- src/class/hid/hid_device.c | 6 +++--- src/common/tusb_timeout.h | 14 +++++++------- src/host/ehci/ehci.c | 8 ++++---- src/portable/nxp/lpc43xx_lpc18xx/hal_lpc43xx.c | 8 ++++---- 4 files changed, 18 insertions(+), 18 deletions(-) (limited to 'src/common') diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index 4ce927725..82c7e3d3f 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -142,14 +142,14 @@ bool tud_hid_keyboard_send_string(const char* str, uint32_t interval_ms) tud_hid_keyboard_send_char(ch); // Blocking delay - timeout_blocking_wait(interval_ms); + tu_timeout_wait(interval_ms); /* Only need to empty report if the next character is NULL or the same with * the current one, else no need to send */ if ( lookahead == ch || lookahead == 0 ) { tud_hid_keyboard_send_report(NULL); - timeout_blocking_wait(interval_ms); + tu_timeout_wait(interval_ms); } } @@ -170,7 +170,7 @@ bool tud_hid_mouse_busy(void) bool tud_hid_mouse_send(hid_mouse_report_t const *p_report) { - VERIFY( tud_mounted() && !tud_hid_mouse_is_busy() ); + VERIFY( tud_mounted() && !tud_hid_mouse_busy() ); hidd_interface_t * p_hid = &_mse_itf; memcpy(p_hid->report_buf, p_report, sizeof(hid_mouse_report_t)); diff --git a/src/common/tusb_timeout.h b/src/common/tusb_timeout.h index 400434708..7c51ff36f 100644 --- a/src/common/tusb_timeout.h +++ b/src/common/tusb_timeout.h @@ -54,26 +54,26 @@ extern "C" { typedef struct { uint32_t start; uint32_t interval; -}timeout_timer_t; +}tu_timeout_t; -static inline void timeout_set(timeout_timer_t* tt, uint32_t msec) +static inline void tu_timeout_set(tu_timeout_t* tt, uint32_t msec) { tt->interval = msec; tt->start = tusb_hal_millis(); } -static inline bool timeout_expired(timeout_timer_t* tt) +static inline bool tu_timeout_expired(tu_timeout_t* tt) { return ( tusb_hal_millis() - tt->start ) >= tt->interval; } -static inline void timeout_blocking_wait(uint32_t msec) +static inline void tu_timeout_wait(uint32_t msec) { - timeout_timer_t tt; - timeout_set(&tt, msec); + tu_timeout_t tt; + tu_timeout_set(&tt, msec); // blocking delay - while ( !timeout_expired(&tt) ) { } + while ( !tu_timeout_expired(&tt) ) { } } #ifdef __cplusplus diff --git a/src/host/ehci/ehci.c b/src/host/ehci/ehci.c index 9e326ec53..ba23319ca 100644 --- a/src/host/ehci/ehci.c +++ b/src/host/ehci/ehci.c @@ -268,14 +268,14 @@ static tusb_error_t hcd_controller_init(uint8_t hostid) static tusb_error_t hcd_controller_stop(uint8_t hostid) { ehci_registers_t* const regs = get_operational_register(hostid); - timeout_timer_t timeout; + tu_timeout_t timeout; regs->usb_cmd_bit.run_stop = 0; - timeout_set(&timeout, 2); // USB Spec: controller has to stop within 16 uframe = 2 frames - while( regs->usb_sts_bit.hc_halted == 0 && !timeout_expired(&timeout)) {} + tu_timeout_set(&timeout, 2); // USB Spec: controller has to stop within 16 uframe = 2 frames + while( regs->usb_sts_bit.hc_halted == 0 && !tu_timeout_expired(&timeout)) {} - return timeout_expired(&timeout) ? TUSB_ERROR_OSAL_TIMEOUT : TUSB_ERROR_NONE; + return tu_timeout_expired(&timeout) ? TUSB_ERROR_OSAL_TIMEOUT : TUSB_ERROR_NONE; } //--------------------------------------------------------------------+ diff --git a/src/portable/nxp/lpc43xx_lpc18xx/hal_lpc43xx.c b/src/portable/nxp/lpc43xx_lpc18xx/hal_lpc43xx.c index 92f9f1cf0..18745d03e 100644 --- a/src/portable/nxp/lpc43xx_lpc18xx/hal_lpc43xx.c +++ b/src/portable/nxp/lpc43xx_lpc18xx/hal_lpc43xx.c @@ -72,11 +72,11 @@ static void hal_controller_reset(uint8_t rhport) // NXP chip powered with non-host mode --> sts bit is not correctly reflected (*p_reg_usbcmd) |= BIT_(1); -// timeout_timer_t timeout; -// timeout_set(&timeout, 2); // should not take longer the time to stop controller - while( ((*p_reg_usbcmd) & BIT_(1)) /*&& !timeout_expired(&timeout)*/) {} +// tu_timeout_t timeout; +// tu_timeout_set(&timeout, 2); // should not take longer the time to stop controller + while( ((*p_reg_usbcmd) & BIT_(1)) /*&& !tu_timeout_expired(&timeout)*/) {} // -// return timeout_expired(&timeout) ? TUSB_ERROR_OSAL_TIMEOUT : TUSB_ERROR_NONE; +// return tu_timeout_expired(&timeout) ? TUSB_ERROR_OSAL_TIMEOUT : TUSB_ERROR_NONE; } bool tusb_hal_init(void) -- cgit v1.3.1 From 5f6cd4903101b0486771efdb2bb435ddf6cf8e7a Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 23 Jul 2018 23:41:14 +0700 Subject: clean up include --- src/class/hid/hid_device.c | 1 - src/common/tusb_common.h | 6 ++---- src/common/tusb_timeout.h | 15 ++++++++++++++- src/host/ehci/ehci.c | 1 - src/host/ohci/ohci.c | 1 - src/portable/nxp/lpc11xx_lpc13xx/dcd_lpc_11uxx_13uxx.c | 1 - src/portable/nxp/lpc43xx_lpc18xx/dcd_lpc43xx.c | 1 - 7 files changed, 16 insertions(+), 10 deletions(-) (limited to 'src/common') diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index 82c7e3d3f..7aca8ef8e 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -45,7 +45,6 @@ // INCLUDE //--------------------------------------------------------------------+ #include "common/tusb_common.h" -#include "common/tusb_timeout.h" #include "hid_device.h" #include "device/usbd_pvt.h" diff --git a/src/common/tusb_common.h b/src/common/tusb_common.h index ddfceabdb..44f31ffe0 100644 --- a/src/common/tusb_common.h +++ b/src/common/tusb_common.h @@ -61,15 +61,13 @@ //------------- TUSB Option Header -------------// #include "tusb_option.h" -//------------- General Header -------------// +//------------- Common Header -------------// #include "tusb_compiler.h" #include "tusb_verify.h" #include "binary.h" #include "tusb_error.h" -#include "tusb_hal.h" #include "tusb_fifo.h" - -//------------- TUSB Header -------------// +#include "tusb_timeout.h" #include "tusb_types.h" //--------------------------------------------------------------------+ diff --git a/src/common/tusb_timeout.h b/src/common/tusb_timeout.h index 7c51ff36f..9d80f5fe7 100644 --- a/src/common/tusb_timeout.h +++ b/src/common/tusb_timeout.h @@ -45,7 +45,6 @@ #define _TUSB_TIMEOUT_H_ #include "tusb_compiler.h" -#include "tusb_hal.h" #ifdef __cplusplus extern "C" { @@ -56,6 +55,8 @@ typedef struct { uint32_t interval; }tu_timeout_t; +extern uint32_t tusb_hal_millis(void); + static inline void tu_timeout_set(tu_timeout_t* tt, uint32_t msec) { tt->interval = msec; @@ -67,6 +68,18 @@ static inline bool tu_timeout_expired(tu_timeout_t* tt) return ( tusb_hal_millis() - tt->start ) >= tt->interval; } +// For used with periodic event to prevent drift +static inline void tu_timeout_reset(tu_timeout_t* tt) +{ + tt->start += tt->interval; +} + +static inline void tu_timeout_restart(tu_timeout_t* tt) +{ + tt->start = tusb_hal_millis(); +} + + static inline void tu_timeout_wait(uint32_t msec) { tu_timeout_t tt; diff --git a/src/host/ehci/ehci.c b/src/host/ehci/ehci.c index ba23319ca..09f2f573a 100644 --- a/src/host/ehci/ehci.c +++ b/src/host/ehci/ehci.c @@ -44,7 +44,6 @@ //--------------------------------------------------------------------+ #include "hal/hal.h" #include "osal/osal.h" -#include "common/tusb_timeout.h" #include "../hcd.h" #include "../usbh_hcd.h" diff --git a/src/host/ohci/ohci.c b/src/host/ohci/ohci.c index 73e9d887e..644dbfa0f 100644 --- a/src/host/ohci/ohci.c +++ b/src/host/ohci/ohci.c @@ -44,7 +44,6 @@ //--------------------------------------------------------------------+ #include "hal/hal.h" #include "osal/osal.h" -#include "common/tusb_timeout.h" #include "../hcd.h" #include "../usbh_hcd.h" diff --git a/src/portable/nxp/lpc11xx_lpc13xx/dcd_lpc_11uxx_13uxx.c b/src/portable/nxp/lpc11xx_lpc13xx/dcd_lpc_11uxx_13uxx.c index 0bb79090e..68eef47e1 100644 --- a/src/portable/nxp/lpc11xx_lpc13xx/dcd_lpc_11uxx_13uxx.c +++ b/src/portable/nxp/lpc11xx_lpc13xx/dcd_lpc_11uxx_13uxx.c @@ -51,7 +51,6 @@ #include "common/tusb_common.h" #include "hal/hal.h" #include "osal/osal.h" -#include "common/tusb_timeout.h" #include "device/dcd.h" #include "usbd_dcd.h" diff --git a/src/portable/nxp/lpc43xx_lpc18xx/dcd_lpc43xx.c b/src/portable/nxp/lpc43xx_lpc18xx/dcd_lpc43xx.c index 6c076baa8..0b48ad1e6 100644 --- a/src/portable/nxp/lpc43xx_lpc18xx/dcd_lpc43xx.c +++ b/src/portable/nxp/lpc43xx_lpc18xx/dcd_lpc43xx.c @@ -46,7 +46,6 @@ #include "common/tusb_common.h" #include "tusb_hal.h" #include "osal/osal.h" -#include "common/tusb_timeout.h" #include "device/dcd.h" #include "dcd_lpc43xx.h" -- cgit v1.3.1 From bd2313aa8bbc81eeff03e4b5b66054ad285214ee Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 24 Jul 2018 18:17:09 +0700 Subject: house keeping --- src/common/tusb_common.h | 16 ++++------------ src/common/tusb_types.h | 22 ++++++++++++++++++++++ 2 files changed, 26 insertions(+), 12 deletions(-) (limited to 'src/common') diff --git a/src/common/tusb_common.h b/src/common/tusb_common.h index 44f31ffe0..58a18f25c 100644 --- a/src/common/tusb_common.h +++ b/src/common/tusb_common.h @@ -137,23 +137,15 @@ #define memclr_(buffer, size) memset((buffer), 0, (size)) #define varclr_(_var) memclr_(_var, sizeof(*(_var))) #define arrclr_(_arr) memclr_(_arr, sizeof(_arr)) - #define arrcount_(_arr) ( sizeof(_arr) / sizeof(_arr[0]) ) -static inline uint8_t const * descriptor_next(uint8_t const p_desc[]) -{ - return p_desc + p_desc[DESC_OFFSET_LEN]; -} - -static inline uint8_t descriptor_type(uint8_t const p_desc[]) +static inline bool mem_all_zero(void const* buffer, uint32_t size) { - return p_desc[DESC_OFFSET_TYPE]; + uint8_t const* p_mem = (uint8_t const*) buffer; + for(uint32_t i=0; i Date: Wed, 25 Jul 2018 16:56:57 +0700 Subject: add scsi start stop unit struct, improve device msc, correctly stall unsupported scsi command --- examples/device/nrf52840/src/msc_device_app.c | 2 +- src/class/msc/msc.h | 23 +++++++++++++++++++++++ src/class/msc/msc_device.c | 27 ++++++++++++++++++--------- src/common/tusb_common.h | 3 +++ src/common/tusb_compiler.h | 14 +++++++------- 5 files changed, 52 insertions(+), 17 deletions(-) (limited to 'src/common') diff --git a/examples/device/nrf52840/src/msc_device_app.c b/examples/device/nrf52840/src/msc_device_app.c index 3f97863e4..d43767119 100644 --- a/examples/device/nrf52840/src/msc_device_app.c +++ b/examples/device/nrf52840/src/msc_device_app.c @@ -112,7 +112,7 @@ int32_t tud_msc_scsi_cb (uint8_t rhport, uint8_t lun, uint8_t const scsi_cmd[16] } // return len must not larger than bufsize - TU_ASSERT( bufsize >= len ); + if ( len > bufsize ) len = bufsize; if ( ptr && len ) { diff --git a/src/class/msc/msc.h b/src/class/msc/msc.h index fc0b8730c..ed9fbfce5 100644 --- a/src/class/msc/msc.h +++ b/src/class/msc/msc.h @@ -298,6 +298,29 @@ typedef struct ATTR_PACKED VERIFY_STATIC( sizeof(scsi_prevent_allow_medium_removal_t) == 6, "size is not correct"); +typedef struct ATTR_PACKED +{ + uint8_t cmd_code; + + uint8_t immded : 1; + uint8_t : 7; + + uint8_t TU_RESERVED; + + uint8_t power_condition_mod : 4; + uint8_t : 4; + + uint8_t start : 1; + uint8_t load_eject : 1; + uint8_t no_flush : 1; + uint8_t : 1; + uint8_t power_condition : 4; + + uint8_t control; +} scsi_start_stop_unit_t; + +VERIFY_STATIC( sizeof(scsi_start_stop_unit_t) == 6, "size is not correct"); + //--------------------------------------------------------------------+ // SCSI MMC //--------------------------------------------------------------------+ diff --git a/src/class/msc/msc_device.c b/src/class/msc/msc_device.c index dc3d47dfd..d9b4c76a8 100644 --- a/src/class/msc/msc_device.c +++ b/src/class/msc/msc_device.c @@ -216,11 +216,14 @@ tusb_error_t mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, tusb_event_t event, u if ( p_cbw->xfer_bytes == 0) { - p_msc->data_len = tud_msc_scsi_cb(rhport, p_cbw->lun, p_cbw->command, NULL, 0); - p_csw->status = (p_msc->data_len == 0) ? MSC_CSW_STATUS_PASSED : MSC_CSW_STATUS_FAILED; + int32_t const cb_result = tud_msc_scsi_cb(rhport, p_cbw->lun, p_cbw->command, NULL, 0); + + p_csw->status = (cb_result == 0) ? MSC_CSW_STATUS_PASSED : MSC_CSW_STATUS_FAILED; + p_msc->data_len = 0; p_msc->stage = MSC_STAGE_STATUS; - TU_ASSERT( p_msc->data_len == 0, TUSB_ERROR_INVALID_PARA); + // stall request since callback return negative + if ( cb_result < 0 ) dcd_edpt_stall(rhport, p_msc->ep_in); } else if ( !BIT_TEST_(p_cbw->dir, 7) ) { @@ -230,7 +233,6 @@ tusb_error_t mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, tusb_event_t event, u else { // IN Transfer - int32_t cb_result; // TODO refactor later @@ -282,8 +284,15 @@ tusb_error_t mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, tusb_event_t event, u cb_result = tud_msc_scsi_cb(rhport, p_cbw->lun, p_cbw->command, _mscd_buf, p_msc->data_len); } - p_csw->status = (cb_result >= 0) ? MSC_CSW_STATUS_PASSED : MSC_CSW_STATUS_FAILED; - p_msc->data_len = (uint32_t) cb_result; + if ( cb_result > 0 ) + { + p_csw->status = MSC_CSW_STATUS_PASSED; + p_msc->data_len = (uint32_t) cb_result; + }else + { + p_csw->status = MSC_CSW_STATUS_FAILED; + p_msc->data_len = 0; + } TU_ASSERT( p_cbw->xfer_bytes >= p_msc->data_len, TUSB_ERROR_INVALID_PARA ); // cannot return more than host expect @@ -292,11 +301,11 @@ tusb_error_t mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, tusb_event_t event, u TU_ASSERT( dcd_edpt_xfer(rhport, p_msc->ep_in, _mscd_buf, p_msc->data_len), TUSB_ERROR_DCD_EDPT_XFER ); }else { - // application does not provide data to response --> possibly unsupported SCSI command - dcd_edpt_stall(rhport, p_msc->ep_in); - + // callback does not provide response's data --> possibly unsupported SCSI command p_csw->status = MSC_CSW_STATUS_FAILED; p_msc->stage = MSC_STAGE_STATUS; + + dcd_edpt_stall(rhport, p_msc->ep_in); } } } diff --git a/src/common/tusb_common.h b/src/common/tusb_common.h index 58a18f25c..e8baa9de4 100644 --- a/src/common/tusb_common.h +++ b/src/common/tusb_common.h @@ -101,6 +101,9 @@ #endif +// for declaration of reserved field, make use of _TU_COUNTER_ +#define TU_RESERVED XSTRING_CONCAT_(reserved, _TU_COUNTER_) + /*------------------------------------------------------------------*/ /* Count number of arguments of __VA_ARGS__ * - reference https://groups.google.com/forum/#!topic/comp.std.c/d-6Mj5Lko_s diff --git a/src/common/tusb_compiler.h b/src/common/tusb_compiler.h index 369c3121a..35a4cc928 100644 --- a/src/common/tusb_compiler.h +++ b/src/common/tusb_compiler.h @@ -49,19 +49,19 @@ #define STRING_CONCAT_(a, b) a##b ///< concat without expand #define XSTRING_CONCAT_(a, b) STRING_CONCAT_(a, b) ///< expand then concat +#if defined __COUNTER__ && __COUNTER__ != __COUNTER__ + #define _TU_COUNTER_ __COUNTER__ +#else + #define _TU_COUNTER_ __LINE__ +#endif + //--------------------------------------------------------------------+ // Compile-time Assert (use VERIFY_STATIC to avoid name conflict) //--------------------------------------------------------------------+ #if defined(__ICCARM__) || (__STDC_VERSION__ >= 201112L ) #define VERIFY_STATIC static_assert #else - #if defined __COUNTER__ && __COUNTER__ != __COUNTER__ - #define _VERIFY_COUNTER __COUNTER__ - #else - #define _VERIFY_COUNTER __LINE__ - #endif - - #define VERIFY_STATIC(const_expr, _mess) enum { XSTRING_CONCAT_(_verify_static_, _VERIFY_COUNTER) = 1/(!!(const_expr)) } + #define VERIFY_STATIC(const_expr, _mess) enum { XSTRING_CONCAT_(_verify_static_, _TU_COUNTER_) = 1/(!!(const_expr)) } #endif // allow debugger to watch any module-wide variables anywhere -- cgit v1.3.1 From 5dd02cbdd37e09de4265105cc9dbb7df00a5f3f7 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 27 Jul 2018 16:59:57 +0700 Subject: house keeping --- examples/obsolete/host/src/msc_cli.c | 2 ++ examples/obsolete/host/src/msc_cli.h | 2 ++ hw/bsp/pca10056/board_pca10056.c | 2 ++ hw/bsp/pca10056/board_pca10056.h | 2 ++ src/class/custom/custom_device.c | 4 +++- src/class/custom/custom_device.h | 4 +++- src/common/tusb_verify.h | 2 ++ src/device/usbd_desc.c | 4 +++- src/device/usbd_pvt.h | 2 ++ src/portable/nordic/nrf5x/dcd_nrf5x.c | 2 ++ src/portable/nordic/nrf5x/hal_nrf5x.c | 2 ++ 11 files changed, 25 insertions(+), 3 deletions(-) (limited to 'src/common') diff --git a/examples/obsolete/host/src/msc_cli.c b/examples/obsolete/host/src/msc_cli.c index aeadb4933..0182a6df9 100644 --- a/examples/obsolete/host/src/msc_cli.c +++ b/examples/obsolete/host/src/msc_cli.c @@ -31,6 +31,8 @@ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + This file is part of the tinyusb stack. */ /**************************************************************************/ diff --git a/examples/obsolete/host/src/msc_cli.h b/examples/obsolete/host/src/msc_cli.h index 052ad05ee..9e41bfd06 100644 --- a/examples/obsolete/host/src/msc_cli.h +++ b/examples/obsolete/host/src/msc_cli.h @@ -31,6 +31,8 @@ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + This file is part of the tinyusb stack. */ /**************************************************************************/ #ifndef _TUSB_MSC_CLI_H_ diff --git a/hw/bsp/pca10056/board_pca10056.c b/hw/bsp/pca10056/board_pca10056.c index 85e32cf2d..c6815917e 100644 --- a/hw/bsp/pca10056/board_pca10056.c +++ b/hw/bsp/pca10056/board_pca10056.c @@ -31,6 +31,8 @@ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + This file is part of the tinyusb stack. */ /**************************************************************************/ diff --git a/hw/bsp/pca10056/board_pca10056.h b/hw/bsp/pca10056/board_pca10056.h index cb477aab8..86544fcc1 100644 --- a/hw/bsp/pca10056/board_pca10056.h +++ b/hw/bsp/pca10056/board_pca10056.h @@ -31,6 +31,8 @@ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + This file is part of the tinyusb stack. */ /**************************************************************************/ #ifndef BOARD_PCA10056_H_ diff --git a/src/class/custom/custom_device.c b/src/class/custom/custom_device.c index c895deb18..2c3783e35 100644 --- a/src/class/custom/custom_device.c +++ b/src/class/custom/custom_device.c @@ -7,7 +7,7 @@ Software License Agreement (BSD License) - Copyright (c) 2018, Adafruit Industries (adafruit.com) + Copyright (c) 2018, hathach (tinyusb.org) All rights reserved. Redistribution and use in source and binary forms, with or without @@ -31,6 +31,8 @@ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + This file is part of the tinyusb stack. */ /**************************************************************************/ diff --git a/src/class/custom/custom_device.h b/src/class/custom/custom_device.h index 3e46c06a7..81a074ce3 100644 --- a/src/class/custom/custom_device.h +++ b/src/class/custom/custom_device.h @@ -7,7 +7,7 @@ Software License Agreement (BSD License) - Copyright (c) 2018, Adafruit Industries (adafruit.com) + Copyright (c) 2018, hathach (tinyusb.org) All rights reserved. Redistribution and use in source and binary forms, with or without @@ -31,6 +31,8 @@ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + This file is part of the tinyusb stack. */ /**************************************************************************/ diff --git a/src/common/tusb_verify.h b/src/common/tusb_verify.h index 95816a0e7..adcdfc97f 100644 --- a/src/common/tusb_verify.h +++ b/src/common/tusb_verify.h @@ -31,6 +31,8 @@ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + This file is part of the tinyusb stack. */ /**************************************************************************/ #ifndef TUSB_VERIFY_H_ diff --git a/src/device/usbd_desc.c b/src/device/usbd_desc.c index 7e9feae90..095464051 100644 --- a/src/device/usbd_desc.c +++ b/src/device/usbd_desc.c @@ -7,7 +7,7 @@ Software License Agreement (BSD License) - Copyright (c) 2018, Adafruit Industries (adafruit.com) + Copyright (c) 2018, hathach (tinyusb.org) All rights reserved. Redistribution and use in source and binary forms, with or without @@ -31,6 +31,8 @@ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + This file is part of the tinyusb stack. */ /**************************************************************************/ diff --git a/src/device/usbd_pvt.h b/src/device/usbd_pvt.h index 343aade77..205057db6 100644 --- a/src/device/usbd_pvt.h +++ b/src/device/usbd_pvt.h @@ -31,6 +31,8 @@ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + This file is part of the tinyusb stack. */ /**************************************************************************/ #ifndef USBD_PVT_H_ diff --git a/src/portable/nordic/nrf5x/dcd_nrf5x.c b/src/portable/nordic/nrf5x/dcd_nrf5x.c index 44d1b93e2..339b8df1f 100644 --- a/src/portable/nordic/nrf5x/dcd_nrf5x.c +++ b/src/portable/nordic/nrf5x/dcd_nrf5x.c @@ -31,6 +31,8 @@ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + This file is part of the tinyusb stack. */ /**************************************************************************/ diff --git a/src/portable/nordic/nrf5x/hal_nrf5x.c b/src/portable/nordic/nrf5x/hal_nrf5x.c index 870f8899a..7ace69ef6 100644 --- a/src/portable/nordic/nrf5x/hal_nrf5x.c +++ b/src/portable/nordic/nrf5x/hal_nrf5x.c @@ -31,6 +31,8 @@ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + This file is part of the tinyusb stack. */ /**************************************************************************/ -- cgit v1.3.1 From 9f61493020821ba7e3226e67b56a062501feb429 Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 28 Jul 2018 12:38:45 +0700 Subject: change HID config, move HID boot config to part of auto descriptor only --- examples/device/nrf52840/src/tusb_config.h | 33 ++++++----- examples/device/nrf52840/src/tusb_descriptors.c | 2 +- src/class/hid/hid_device.c | 49 ++++++++++----- src/class/hid/hid_device.h | 34 ++++++++--- src/common/tusb_error.h | 2 + src/device/usbd.c | 6 +- src/device/usbd.h | 2 +- src/device/usbd_desc.c | 79 +++++++++++-------------- src/tusb.h | 2 +- src/tusb_option.h | 2 - tests/lpc175x_6x/test/test_usbd.c | 2 +- 11 files changed, 120 insertions(+), 93 deletions(-) (limited to 'src/common') diff --git a/examples/device/nrf52840/src/tusb_config.h b/examples/device/nrf52840/src/tusb_config.h index aad189429..9ef739bcd 100644 --- a/examples/device/nrf52840/src/tusb_config.h +++ b/examples/device/nrf52840/src/tusb_config.h @@ -61,33 +61,38 @@ // DEVICE CONFIGURATION //-------------------------------------------------------------------- -/*------------- Core -------------*/ +#define CFG_TUD_ENDOINT0_SIZE 64 + +/*------------- Descriptors -------------*/ + +/* Enable auto generated descriptor, tinyusb will try its best to create + * descriptor ( device, configuration, hid ) that matches enabled CFG_* in this file + * + * Note: All CFG_TUD_DESC_* are relevant only if CFG_TUD_DESC_AUTO is enabled + */ #define CFG_TUD_DESC_AUTO 1 +/* USB VID/PID if not defined, tinyusb to use default value + * Note: different class combination e.g CDC and (CDC + MSC) should have different + * PID since Host OS will "remembered" device driver after the first plug */ // #define CFG_TUD_DESC_VID 0xCAFE // #define CFG_TUD_DESC_PID 0x0001 -#define CFG_TUD_ENDOINT0_SIZE 64 +/* Use Boot Protocol for Keyboard, Mouse. Enable this will create separated HID interface + * require more IN endpoints. If disabled, they they are all packed into a single + * multiple report interface called "Generic". + */ +#define CFG_TUD_DESC_BOOT_KEYBOARD 1 +#define CFG_TUD_DESC_BOOT_MOUSE 1 //------------- CLASS -------------// #define CFG_TUD_CDC 1 #define CFG_TUD_MSC 1 +#define CFG_TUD_HID 1 #define CFG_TUD_HID_KEYBOARD 1 #define CFG_TUD_HID_MOUSE 1 -//#define CFG_TUD_HID_GENERIC 0 - -/* Enable boot protocol will create separated HID interface for Keyboard, - * Consumer Key and Mouse --> require more In endpoints. Otherwise they - * are all packed into a single Multiple Report Interface. - * - * Note: If your device is meant to work with simple host running on - * an MCU (e.g with tinyusb host), boot protocol should be enabled. - */ -//#define CFG_TUD_HID_BOOT_PROTOCOL 1 -#define CFG_TUD_HID_KEYBOARD_BOOT 1 -#define CFG_TUD_HID_MOUSE_BOOT 1 //-------------------------------------------------------------------- // CDC diff --git a/examples/device/nrf52840/src/tusb_descriptors.c b/examples/device/nrf52840/src/tusb_descriptors.c index 7dc3642aa..2b219c87a 100644 --- a/examples/device/nrf52840/src/tusb_descriptors.c +++ b/examples/device/nrf52840/src/tusb_descriptors.c @@ -91,7 +91,7 @@ tud_desc_set_t tud_desc_set = .hid_report = { - .composite = NULL, + .generic = NULL, .boot_keyboard = NULL, .boot_mouse = NULL } diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index e58b7dc5c..bd9d800d1 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -38,7 +38,7 @@ #include "tusb_option.h" -#if (TUSB_OPT_DEVICE_ENABLED && TUD_OPT_HID_ENABLED) +#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_HID) #define _TINY_USB_SOURCE_FILE_ //--------------------------------------------------------------------+ @@ -82,9 +82,16 @@ CFG_TUSB_ATTR_USBRAM static hidd_interface_t _kbd_itf; CFG_TUSB_ATTR_USBRAM static hidd_interface_t _mse_itf; #endif -#if 0 // CFG_TUD_HID_BOOT_PROTOCOL -CFG_TUSB_ATTR_USBRAM static hidd_interface_t _composite_itf; -#endif +CFG_TUSB_ATTR_USBRAM static hidd_interface_t _hidd_itf; + + +//--------------------------------------------------------------------+ +// HID GENERIC API +//--------------------------------------------------------------------+ +bool tud_hid_generic_ready(void) +{ + +} //--------------------------------------------------------------------+ // KEYBOARD APPLICATION API @@ -173,6 +180,7 @@ bool tud_hid_keyboard_key_sequence(const char* str, uint32_t interval_ms) } } + return true; } #endif // CFG_TUD_HID_ASCII_TO_KEYCODE_LOOKUP @@ -268,23 +276,25 @@ void hidd_reset(uint8_t rhport) #endif } -tusb_error_t hidd_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint16_t *p_length) +tusb_error_t hidd_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint16_t *p_len) { uint8_t const *p_desc = (uint8_t const *) desc_itf; //------------- HID descriptor -------------// p_desc += p_desc[DESC_OFFSET_LEN]; tusb_hid_descriptor_hid_t const *desc_hid = (tusb_hid_descriptor_hid_t const *) p_desc; - TU_ASSERT(HID_DESC_TYPE_HID == desc_hid->bDescriptorType, TUSB_ERROR_HIDD_DESCRIPTOR_INTERFACE); + TU_ASSERT(HID_DESC_TYPE_HID == desc_hid->bDescriptorType, ERR_TUD_INVALID_DESCRIPTOR); //------------- Endpoint Descriptor -------------// p_desc += p_desc[DESC_OFFSET_LEN]; tusb_desc_endpoint_t const *desc_edpt = (tusb_desc_endpoint_t const *) p_desc; - TU_ASSERT(TUSB_DESC_ENDPOINT == desc_edpt->bDescriptorType, TUSB_ERROR_HIDD_DESCRIPTOR_INTERFACE); + TU_ASSERT(TUSB_DESC_ENDPOINT == desc_edpt->bDescriptorType, ERR_TUD_INVALID_DESCRIPTOR); + + *p_len = 0; if (desc_itf->bInterfaceSubClass == HID_SUBCLASS_BOOT) { - TU_ASSERT(desc_itf->bInterfaceProtocol == HID_PROTOCOL_KEYBOARD || desc_itf->bInterfaceProtocol == HID_PROTOCOL_MOUSE, TUSB_ERROR_HIDD_DESCRIPTOR_INTERFACE); + TU_ASSERT(desc_itf->bInterfaceProtocol == HID_PROTOCOL_KEYBOARD || desc_itf->bInterfaceProtocol == HID_PROTOCOL_MOUSE, ERR_TUD_INVALID_DESCRIPTOR); hidd_interface_t * p_hid = NULL; @@ -293,7 +303,6 @@ tusb_error_t hidd_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, u { p_hid = &_kbd_itf; p_hid->report_desc = tud_desc_set.hid_report.boot_keyboard; - p_hid->boot_protocol = CFG_TUD_HID_KEYBOARD_BOOT; // default mode is BOOT if enabled p_hid->get_report_cb = tud_hid_keyboard_get_report_cb; p_hid->set_report_cb = tud_hid_keyboard_set_report_cb; } @@ -304,13 +313,12 @@ tusb_error_t hidd_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, u { p_hid = &_mse_itf; p_hid->report_desc = tud_desc_set.hid_report.boot_mouse; - p_hid->boot_protocol = CFG_TUD_HID_MOUSE_BOOT; // default mode is BOOT if enabled p_hid->get_report_cb = tud_hid_mouse_get_report_cb; p_hid->set_report_cb = tud_hid_mouse_set_report_cb; } #endif - TU_ASSERT(p_hid, TUSB_ERROR_HIDD_DESCRIPTOR_INTERFACE); + TU_ASSERT(p_hid, ERR_TUD_INVALID_DESCRIPTOR); VERIFY(p_hid->report_desc, TUSB_ERROR_DESCRIPTOR_CORRUPTED); TU_ASSERT( dcd_edpt_open(rhport, desc_edpt), TUSB_ERROR_DCD_FAILED ); @@ -319,15 +327,26 @@ tusb_error_t hidd_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, u p_hid->itf_num = desc_itf->bInterfaceNumber; p_hid->ep_in = desc_edpt->bEndpointAddress; p_hid->report_id = 0; + p_hid->boot_protocol = true; // default mode is BOOT - *p_length = sizeof(tusb_desc_interface_t) + sizeof(tusb_hid_descriptor_hid_t) + sizeof(tusb_desc_endpoint_t); + *p_len = sizeof(tusb_desc_interface_t) + sizeof(tusb_hid_descriptor_hid_t) + sizeof(tusb_desc_endpoint_t); } else { // TODO HID generic + hidd_interface_t * p_hid = &_hidd_itf; + + p_hid->itf_num = desc_itf->bInterfaceNumber; + p_hid->ep_in = desc_edpt->bEndpointAddress; + // TODO parse report ID for keyboard, mouse - *p_length = 0; - return TUSB_ERROR_HIDD_DESCRIPTOR_INTERFACE; + p_hid->report_id = 0; + p_hid->report_len = 0; + p_hid->report_desc = NULL; + //p_hid->get_report_cb = tud_hid_get_report_cb; + //p_hid->set_report_cb = tud_hid_set_report_cb; + + return ERR_TUD_INVALID_DESCRIPTOR; } return TUSB_ERROR_NONE; @@ -352,7 +371,7 @@ tusb_error_t hidd_control_request_st(uint8_t rhport, tusb_control_request_t cons { STASK_ASSERT ( p_hid->report_len <= CFG_TUD_CTRL_BUFSIZE ); - // use device control buffer (in USB SRAM) + // use device control buffer memcpy(_usbd_ctrl_buf, p_hid->report_desc, p_hid->report_len); usbd_control_xfer_st(rhport, p_request->bmRequestType_bit.direction, _usbd_ctrl_buf, p_hid->report_len); diff --git a/src/class/hid/hid_device.h b/src/class/hid/hid_device.h index e8f5b40f4..06c07d446 100644 --- a/src/class/hid/hid_device.h +++ b/src/class/hid/hid_device.h @@ -49,8 +49,19 @@ //--------------------------------------------------------------------+ -// KEYBOARD APPLICATION API +// HID GENERIC API //--------------------------------------------------------------------+ +bool tud_hid_generic_ready(void); +bool tud_hid_generic_report(void); + +/*------------- Callbacks -------------*/ +ATTR_WEAK uint16_t tud_hid_get_report_cb(uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen); +ATTR_WEAK void tud_hid_set_report_cb(uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize); + +//--------------------------------------------------------------------+ +// KEYBOARD API +//--------------------------------------------------------------------+ +#if CFG_TUD_HID_KEYBOARD /** \addtogroup ClassDriver_HID_Keyboard Keyboard * @{ */ /** \defgroup Keyboard_Device Device @@ -78,7 +89,9 @@ typedef struct{ extern const hid_ascii_to_keycode_entry_t HID_ASCII_TO_KEYCODE[128]; #endif -/*------------- Callbacks, ATTR_WEAK means optional -------------*/ +#endif + +/*------------- Callbacks -------------*/ /** Callback invoked when USB host request \ref HID_REQ_CONTROL_GET_REPORT. * \param[in] report_type specify which report (INPUT, OUTPUT, FEATURE) that host requests @@ -109,8 +122,9 @@ ATTR_WEAK void tud_hid_keyboard_set_report_cb(hid_report_type_t report_type, uin /** @} */ //--------------------------------------------------------------------+ -// MOUSE APPLICATION API +// MOUSE API //--------------------------------------------------------------------+ +#if CFG_TUD_HID_MOUSE /** \addtogroup ClassDriver_HID_Mouse Mouse * @{ */ /** \defgroup Mouse_Device Device @@ -141,10 +155,10 @@ static inline bool tud_hid_mouse_button_release(void) /*------------- Callbacks -------------*/ -/** \brief Callback function that is invoked when USB host request \ref HID_REQUEST_CONTROL_GET_REPORT - * via control endpoint. +/** + * Callback function that is invoked when USB host request \ref HID_REQ_CONTROL_GET_REPORT. * \param[in] report_type specify which report (INPUT, OUTPUT, FEATURE) that host requests - * \param[out] buffer buffer that application need to update, value must be accessible by USB controller (see \ref CFG_TUSB_ATTR_USBRAM) + * \param[out] buffer buffer that application need to update, value must be accessible by USB controller (see \ref CFG_TUSB_ATTR_USBRAM) * \param[in] reqlen number of bytes that host requested * \retval non-zero Actual number of bytes in the response's buffer. * \retval zero indicates the current request is not supported. Tinyusb device stack will reject the request by @@ -154,8 +168,8 @@ static inline bool tud_hid_mouse_button_release(void) */ ATTR_WEAK uint16_t tud_hid_mouse_get_report_cb(hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen); -/** \brief Callback function that is invoked when USB host request \ref HID_REQUEST_CONTROL_SET_REPORT - * via control endpoint. +/** + * Callback function that is invoked when USB host request \ref HID_REQ_CONTROL_SET_REPORT. * \param[in] report_type specify which report (INPUT, OUTPUT, FEATURE) that host requests * \param[in] buffer buffer containing the report's data * \param[in] bufsize number of bytes in the \a p_report_data @@ -166,13 +180,15 @@ ATTR_WEAK void tud_hid_mouse_set_report_cb(hid_report_type_t report_type, uint8_ //ATTR_WEAK void tud_hid_mouse_set_protocol_cb(bool boot_protocol); +#endif + /** @} */ /** @} */ //--------------------------------------------------------------------+ -// USBD-CLASS DRIVER API +// INTERNAL API //--------------------------------------------------------------------+ #ifdef _TINY_USB_SOURCE_FILE_ diff --git a/src/common/tusb_error.h b/src/common/tusb_error.h index 339f6ced1..e7c7f69f9 100644 --- a/src/common/tusb_error.h +++ b/src/common/tusb_error.h @@ -91,6 +91,8 @@ ENTRY(TUSB_ERROR_USBD_DEVICE_NOT_CONFIGURED )\ ENTRY(TUSB_ERROR_NOT_ENOUGH_MEMORY )\ ENTRY(TUSB_ERROR_FAILED )\ + \ + ENTRY(ERR_TUD_INVALID_DESCRIPTOR) /// \brief Error Code returned diff --git a/src/device/usbd.c b/src/device/usbd.c index 8f406d0bd..f6b55a81d 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -116,7 +116,7 @@ static usbd_class_driver_t const usbd_class_drivers[] = #endif - #if TUD_OPT_HID_ENABLED + #if CFG_TUD_HID { .class_code = TUSB_CLASS_HID, .init = hidd_init, @@ -318,12 +318,12 @@ static void usbd_reset(uint8_t rhport) tud_desc_set.device = (uint8_t const*) &_desc_auto_device; tud_desc_set.config = _desc_auto_config; - #if CFG_TUD_HID_KEYBOARD && CFG_TUD_HID_KEYBOARD_BOOT + #if CFG_TUD_HID_KEYBOARD && CFG_TUD_DESC_BOOT_KEYBOARD extern uint8_t const _desc_auto_hid_kbd_report[]; tud_desc_set.hid_report.boot_keyboard = _desc_auto_hid_kbd_report; #endif - #if CFG_TUD_HID_MOUSE && CFG_TUD_HID_MOUSE_BOOT + #if CFG_TUD_HID_MOUSE && CFG_TUD_DESC_BOOT_MOUSE extern uint8_t const _desc_auto_hid_mse_report[]; tud_desc_set.hid_report.boot_mouse = _desc_auto_hid_mse_report; #endif diff --git a/src/device/usbd.h b/src/device/usbd.h index 8413aa15e..8ef1209e1 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -66,7 +66,7 @@ typedef struct { uint16_t string_count; struct { - uint8_t const* composite; + uint8_t const* generic; uint8_t const* boot_keyboard; uint8_t const* boot_mouse; } hid_report; diff --git a/src/device/usbd_desc.c b/src/device/usbd_desc.c index b1bb07809..1a37c6f58 100644 --- a/src/device/usbd_desc.c +++ b/src/device/usbd_desc.c @@ -47,9 +47,13 @@ #if CFG_TUD_DESC_AUTO +// Generic (multiple) Report : Keyboard + Mouse + Gamepad + Joystick +#define HID_GENERIC (CFG_TUD_HID && ( (CFG_TUD_HID_KEYBOARD && !CFG_TUD_DESC_BOOT_KEYBOARD) || \ + (CFG_TUD_HID_MOUSE && !CFG_TUD_DESC_BOOT_MOUSE) )) + /*------------- VID/PID -------------*/ #ifndef CFG_TUD_DESC_VID -#define CFG_TUD_DESC_VID 0xCAFE +#define CFG_TUD_DESC_VID 0xCAFE #endif #ifndef CFG_TUD_DESC_PID @@ -58,11 +62,11 @@ * Same VID/PID with different interface e.g MSC (first), then CDC (later) will possibly cause system error on PC. * * Auto ProductID layout's Bitmap: - * [MSB] HID Generic | HID Composite | HID Mouse | HID Keyboard | MSC | CDC [LSB] + * [MSB] HID Generic | Boot Mouse | Boot Keyboard | MSC | CDC [LSB] */ -#define _PID_MAP(itf, n) ( (CFG_TUD_##itf) << (n) ) -#define CFG_TUD_DESC_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | \ - _PID_MAP(HID_KEYBOARD, 2) | _PID_MAP(HID_MOUSE, 3) /*| _PID_MAP(HID_GENERIC, 5)*/ ) +#define _PID_MAP(itf, n) ( (CFG_TUD_##itf) << (n) ) +#define CFG_TUD_DESC_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \ + _PID_MAP(HID_KEYBOARD, 2) | _PID_MAP(HID_MOUSE, 3) | (HID_GENERIC << 4) ) #endif /*------------- Interface Numbering -------------*/ @@ -76,8 +80,8 @@ #define ITF_NUM_HID_KBD (ITF_NUM_MSC + CFG_TUD_MSC) #define ITF_NUM_HID_MSE (ITF_NUM_HID_KBD + CFG_TUD_HID_KEYBOARD) -#define ITF_TOTAL (ITF_NUM_HID_MSE + CFG_TUD_HID_MOUSE) - +#define ITF_NUM_HID_GEN (ITF_NUM_HID_MSE + CFG_TUD_HID_MOUSE) +#define ITF_TOTAL (ITF_NUM_HID_GEN + HID_GENERIC) /*------------- Endpoint Numbering & Size -------------*/ #define _EP_IN(x) (0x80 | (x)) @@ -96,23 +100,24 @@ // HID Keyboard with boot protocol -#if CFG_TUD_HID_KEYBOARD && CFG_TUD_HID_KEYBOARD_BOOT +#if CFG_TUD_HID_KEYBOARD && CFG_TUD_DESC_BOOT_KEYBOARD #define EP_HID_KBD_BOOT _EP_IN (ITF_NUM_HID_KBD+1) #define EP_HID_KBD_BOOT_SZ 8 - #endif // HID Mouse with boot protocol -#if CFG_TUD_HID_MOUSE && CFG_TUD_HID_MOUSE_BOOT +#if CFG_TUD_HID_MOUSE && CFG_TUD_DESC_BOOT_MOUSE #define EP_HID_MSE_BOOT _EP_IN (ITF_NUM_HID_MSE+1) #define EP_HID_MSE_BOOT_SZ 8 #endif -#if 0 // CFG_TUD_HID_BOOT_PROTOCOL + + +#if HID_GENERIC // HID composite = keyboard + mouse -#define EP_HID_COMP _EP_IN (ITF_NUM_HID_KBD+1) -#define EP_HID_COMP_SIZE 16 +#define EP_HID_GEN _EP_IN (EP_HID_MSE_BOOT+1) +#define EP_HID_GEN_SIZE 16 #endif @@ -307,7 +312,7 @@ typedef struct ATTR_PACKED #endif //------------- HID -------------// -#if CFG_TUD_HID_KEYBOARD && CFG_TUD_HID_KEYBOARD_BOOT +#if CFG_TUD_HID_KEYBOARD && CFG_TUD_DESC_BOOT_KEYBOARD struct ATTR_PACKED { tusb_desc_interface_t itf; @@ -316,7 +321,7 @@ typedef struct ATTR_PACKED } hid_kbd_boot; #endif -#if CFG_TUD_HID_MOUSE && CFG_TUD_HID_MOUSE_BOOT +#if CFG_TUD_HID_MOUSE && CFG_TUD_DESC_BOOT_MOUSE struct ATTR_PACKED { tusb_desc_interface_t itf; @@ -325,20 +330,18 @@ typedef struct ATTR_PACKED } hid_mse_boot; #endif -#if 0 // CFG_TUD_HID_BOOT_PROTOCOL +#if HID_GENERIC -#if CFG_TUD_HID_KEYBOARD || CFG_TUD_HID_MOUSE struct ATTR_PACKED { tusb_desc_interface_t itf; tusb_hid_descriptor_hid_t hid_desc; tusb_desc_endpoint_t ep_in; - #if CFG_TUD_HID_KEYBOARD + #if 0 // CFG_TUD_HID_KEYBOARD tusb_desc_endpoint_t ep_out; #endif - } hid_composite; -#endif + } hid_generic; #endif @@ -513,7 +516,7 @@ desc_auto_cfg_t const _desc_auto_config_struct = }, #endif // msc -#if CFG_TUD_HID_KEYBOARD && CFG_TUD_HID_KEYBOARD_BOOT +#if CFG_TUD_HID_KEYBOARD && CFG_TUD_DESC_BOOT_KEYBOARD .hid_kbd_boot = { .itf = @@ -553,7 +556,7 @@ desc_auto_cfg_t const _desc_auto_config_struct = #endif // boot keyboard //------------- HID Mouse -------------// -#if CFG_TUD_HID_MOUSE && CFG_TUD_HID_MOUSE_BOOT +#if CFG_TUD_HID_MOUSE && CFG_TUD_DESC_BOOT_MOUSE .hid_mse_boot = { .itf = @@ -593,23 +596,22 @@ desc_auto_cfg_t const _desc_auto_config_struct = #endif // boot mouse -#if 0 +#if HID_GENERIC -#if CFG_TUD_HID_KEYBOARD || CFG_TUD_HID_MOUSE - //------------- HID Keyboard + Mouse (multiple reports) -------------// + //------------- HID Generic Multiple report -------------// .hid_composite = { .itf = { .bLength = sizeof(tusb_desc_interface_t), .bDescriptorType = TUSB_DESC_INTERFACE, - .bInterfaceNumber = ITF_NUM_HID_KBD, + .bInterfaceNumber = ITF_NUM_HID_GEN, .bAlternateSetting = 0x00, .bNumEndpoints = 2, .bInterfaceClass = TUSB_CLASS_HID, .bInterfaceSubClass = 0, .bInterfaceProtocol = 0, - .iInterface = 4 + CFG_TUD_CDC + CFG_TUD_MSC, + .iInterface = 0, // 4 + CFG_TUD_CDC + CFG_TUD_MSC, }, .hid_desc = @@ -620,41 +622,26 @@ desc_auto_cfg_t const _desc_auto_config_struct = .bCountryCode = HID_Local_NotSupported, .bNumDescriptors = 1, .bReportType = HID_DESC_TYPE_REPORT, - .wReportLength = sizeof(_desc_auto_hid_composite_report) + .wReportLength = sizeof(_desc_auto_hid_generic_report) }, .ep_in = { .bLength = sizeof(tusb_desc_endpoint_t), .bDescriptorType = TUSB_DESC_ENDPOINT, - .bEndpointAddress = EP_HID_COMP, + .bEndpointAddress = EP_HID_GEN, .bmAttributes = { .xfer = TUSB_XFER_INTERRUPT }, - .wMaxPacketSize = { .size = EP_HID_COMP_SIZE }, + .wMaxPacketSize = { .size = EP_HID_GEN_SIZE }, .bInterval = 0x0A } } -#endif -#endif // boot protocol +#endif // hid generic }; uint8_t const * const _desc_auto_config = (uint8_t const*) &_desc_auto_config_struct; #endif -/*------------------------------------------------------------------*/ -/* MACRO TYPEDEF CONSTANT ENUM - *------------------------------------------------------------------*/ - -/*------------------------------------------------------------------*/ -/* VARIABLE DECLARATION - *------------------------------------------------------------------*/ - -/*------------------------------------------------------------------*/ -/* FUNCTION DECLARATION - *------------------------------------------------------------------*/ - - - #endif diff --git a/src/tusb.h b/src/tusb.h index 8f25e2867..01fdf5ed3 100644 --- a/src/tusb.h +++ b/src/tusb.h @@ -76,7 +76,7 @@ #if TUSB_OPT_DEVICE_ENABLED #include "device/usbd.h" - #if TUD_OPT_HID_ENABLED + #if CFG_TUD_HID #include "class/hid/hid_device.h" #endif diff --git a/src/tusb_option.h b/src/tusb_option.h index a7b18d504..251fb2470 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -151,8 +151,6 @@ //-------------------------------------------------------------------- #if TUSB_OPT_DEVICE_ENABLED - #define TUD_OPT_HID_ENABLED ( CFG_TUD_HID_KEYBOARD + CFG_TUD_HID_MOUSE ) - #ifndef CFG_TUD_ENDOINT0_SIZE #define CFG_TUD_ENDOINT0_SIZE 64 #endif diff --git a/tests/lpc175x_6x/test/test_usbd.c b/tests/lpc175x_6x/test/test_usbd.c index b70f4592c..1dd041a41 100644 --- a/tests/lpc175x_6x/test/test_usbd.c +++ b/tests/lpc175x_6x/test/test_usbd.c @@ -87,7 +87,7 @@ tusb_error_t stub_hidd_init(uint8_t coreid, tusb_desc_interface_t const* p_inter void class_init_epxect(void) { -#if TUD_OPT_HID_ENABLED +#if CFG_TUD_HID hidd_init_StubWithCallback(stub_hidd_init); #endif } -- cgit v1.3.1 From 683bb574e723685f38082f2461f2fa8eb9900c90 Mon Sep 17 00:00:00 2001 From: hathach Date: Sun, 29 Jul 2018 14:03:48 +0700 Subject: hid device enhance --- examples/device/nrf52840/src/tusb_config.h | 13 ++++---- src/class/hid/hid_device.h | 16 +++++++--- src/common/tusb_error.h | 3 +- src/device/usbd.c | 6 ++-- src/device/usbd_desc.c | 51 +++++++++++++++--------------- src/tusb_option.h | 8 ++--- 6 files changed, 54 insertions(+), 43 deletions(-) (limited to 'src/common') diff --git a/examples/device/nrf52840/src/tusb_config.h b/examples/device/nrf52840/src/tusb_config.h index 3b5ec360d..9e6b01616 100644 --- a/examples/device/nrf52840/src/tusb_config.h +++ b/examples/device/nrf52840/src/tusb_config.h @@ -78,13 +78,6 @@ // #define CFG_TUD_DESC_VID 0xCAFE // #define CFG_TUD_DESC_PID 0x0001 -/* Use Boot Protocol for Keyboard, Mouse. Enable this will create separated HID interface - * require more IN endpoints. If disabled, they they are all packed into a single - * multiple report interface called "Generic". - */ -#define CFG_TUD_DESC_BOOT_KEYBOARD 0 -#define CFG_TUD_DESC_BOOT_MOUSE 0 - //------------- CLASS -------------// #define CFG_TUD_CDC 1 #define CFG_TUD_MSC 1 @@ -93,6 +86,12 @@ #define CFG_TUD_HID_KEYBOARD 1 #define CFG_TUD_HID_MOUSE 1 +/* Use Boot Protocol for Keyboard, Mouse. Enable this will create separated HID interface + * require more IN endpoints. If disabled, they they are all packed into a single + * multiple report interface called "Generic". */ +#define CFG_TUD_HID_KEYBOARD_BOOT 1 +#define CFG_TUD_HID_MOUSE_BOOT 1 + //-------------------------------------------------------------------- // CDC diff --git a/src/class/hid/hid_device.h b/src/class/hid/hid_device.h index 31d4a0c2f..5f21878e0 100644 --- a/src/class/hid/hid_device.h +++ b/src/class/hid/hid_device.h @@ -48,14 +48,22 @@ #endif //--------------------------------------------------------------------+ -// Class Driver Configuration +// Class Driver Default Configure & Validation //--------------------------------------------------------------------+ -#if !CFG_TUD_HID_KEYBOARD && CFG_TUD_DESC_BOOT_KEYBOARD +#ifndef CFG_TUD_HID_KEYBOARD_BOOT +#define CFG_TUD_HID_KEYBOARD_BOOT 0 +#endif + +#ifndef CFG_TUD_HID_MOUSE_BOOT +#define CFG_TUD_HID_MOUSE_BOOT 0 +#endif + +#if !CFG_TUD_HID_KEYBOARD && CFG_TUD_HID_KEYBOARD_BOOT #error CFG_TUD_HID_KEYBOARD must be enabled #endif -#if !CFG_TUD_HID_MOUSE && CFG_TUD_DESC_BOOT_MOUSE -#error CFG_TUD_HID_MOUSE must be enabled +#if !CFG_TUD_HID_MOUSE && CFG_TUD_HID_MOUSE_BOOT +#error CFG_TUD_HID_MOUSE must be enabled #endif diff --git a/src/common/tusb_error.h b/src/common/tusb_error.h index e7c7f69f9..677fc44e4 100644 --- a/src/common/tusb_error.h +++ b/src/common/tusb_error.h @@ -92,7 +92,8 @@ ENTRY(TUSB_ERROR_NOT_ENOUGH_MEMORY )\ ENTRY(TUSB_ERROR_FAILED )\ \ - ENTRY(ERR_TUD_INVALID_DESCRIPTOR) + ENTRY(ERR_TUD_INVALID_DESCRIPTOR) \ + ENTRY(ERR_TUD_EDPT_OPEN_FAILED) \ /// \brief Error Code returned diff --git a/src/device/usbd.c b/src/device/usbd.c index 7c302cc77..5f83728ef 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -318,12 +318,13 @@ static void usbd_reset(uint8_t rhport) tud_desc_set.device = (uint8_t const*) &_desc_auto_device; tud_desc_set.config = _desc_auto_config; - #if CFG_TUD_HID_KEYBOARD && CFG_TUD_DESC_BOOT_KEYBOARD +#if CFG_TUD_HID + #if CFG_TUD_HID_KEYBOARD && CFG_TUD_HID_KEYBOARD_BOOT extern uint8_t const _desc_auto_hid_boot_kbd_report[]; tud_desc_set.hid_report.boot_keyboard = _desc_auto_hid_boot_kbd_report; #endif - #if CFG_TUD_HID_MOUSE && CFG_TUD_DESC_BOOT_MOUSE + #if CFG_TUD_HID_MOUSE && CFG_TUD_HID_MOUSE_BOOT extern uint8_t const _desc_auto_hid_boot_mse_report[]; tud_desc_set.hid_report.boot_mouse = _desc_auto_hid_boot_mse_report; #endif @@ -332,6 +333,7 @@ static void usbd_reset(uint8_t rhport) extern uint8_t const _desc_auto_hid_generic_report[]; tud_desc_set.hid_report.generic = _desc_auto_hid_generic_report; #endif +#endif // CFG_TUD_HID #endif // CFG_TUD_DESC_AUTO diff --git a/src/device/usbd_desc.c b/src/device/usbd_desc.c index 8d3095503..8f147aa67 100644 --- a/src/device/usbd_desc.c +++ b/src/device/usbd_desc.c @@ -45,6 +45,10 @@ #if CFG_TUD_DESC_AUTO +//--------------------------------------------------------------------+ +// Auto Description Default Configure & Validation +//--------------------------------------------------------------------+ + /*------------- VID/PID -------------*/ #ifndef CFG_TUD_DESC_VID #define CFG_TUD_DESC_VID 0xCAFE @@ -63,17 +67,20 @@ _PID_MAP(HID_KEYBOARD, 2) | _PID_MAP(HID_MOUSE, 3) | (TUD_OPT_HID_GENERIC << 4) ) #endif +//--------------------------------------------------------------------+ +// Interface & Endpoint mapping +//--------------------------------------------------------------------+ + /*------------- Interface Numbering -------------*/ -/* The order as follows: CDC, MSC, HID - * If a interface is not enabled, the later will take its place - */ +/* The order as follows: CDC, MSC, Boot Keyboard, Boot Mouse, HID Generic + * If an interface is not enabled, the later will take its place */ #define ITF_NUM_CDC 0 #define ITF_NUM_MSC (ITF_NUM_CDC + 2*CFG_TUD_CDC) #define ITF_NUM_HID_BOOT_KBD (ITF_NUM_MSC + CFG_TUD_MSC) -#define ITF_NUM_HID_BOOT_MSE (ITF_NUM_HID_BOOT_KBD + CFG_TUD_DESC_BOOT_KEYBOARD) -#define ITF_NUM_HID_GEN (ITF_NUM_HID_BOOT_MSE + CFG_TUD_DESC_BOOT_MOUSE) +#define ITF_NUM_HID_BOOT_MSE (ITF_NUM_HID_BOOT_KBD + CFG_TUD_HID_KEYBOARD_BOOT) +#define ITF_NUM_HID_GEN (ITF_NUM_HID_BOOT_MSE + CFG_TUD_HID_MOUSE_BOOT) #define ITF_TOTAL (ITF_NUM_HID_GEN + TUD_OPT_HID_GENERIC) @@ -112,8 +119,6 @@ /*------------- Keyboard Descriptor -------------*/ -#if CFG_TUD_HID_KEYBOARD - #define HID_REPORT_KEYBOARD(...) \ HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ) ,\ HID_USAGE ( HID_USAGE_DESKTOP_KEYBOARD ) ,\ @@ -154,14 +159,7 @@ HID_OUTPUT ( HID_CONSTANT ) ,\ HID_COLLECTION_END \ -#if CFG_TUD_DESC_BOOT_KEYBOARD -uint8_t const _desc_auto_hid_boot_kbd_report[] = { HID_REPORT_KEYBOARD() }; -#endif - -#endif // hid keyboard - /*------------- Mouse Descriptor -------------*/ -#if CFG_TUD_HID_MOUSE #define HID_REPORT_MOUSE(...) \ HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ) ,\ HID_USAGE ( HID_USAGE_DESKTOP_MOUSE ) ,\ @@ -201,23 +199,26 @@ uint8_t const _desc_auto_hid_boot_kbd_report[] = { HID_REPORT_KEYBOARD() }; HID_COLLECTION_END ,\ HID_COLLECTION_END \ -#if CFG_TUD_DESC_BOOT_MOUSE -uint8_t const _desc_auto_hid_boot_mse_report[] = { HID_REPORT_MOUSE() }; -#endif - -#endif // hid mouse /*------------- Generic (composite) Descriptor -------------*/ +#if CFG_TUD_HID_KEYBOARD && CFG_TUD_HID_KEYBOARD_BOOT +uint8_t const _desc_auto_hid_boot_kbd_report[] = { HID_REPORT_KEYBOARD() }; +#endif + +#if CFG_TUD_HID_MOUSE && CFG_TUD_HID_MOUSE_BOOT +uint8_t const _desc_auto_hid_boot_mse_report[] = { HID_REPORT_MOUSE() }; +#endif #if TUD_OPT_HID_GENERIC +// TODO report ID uint8_t const _desc_auto_hid_generic_report[] = { -#if !CFG_TUD_DESC_BOOT_KEYBOARD +#if CFG_TUD_HID_KEYBOARD && !CFG_TUD_HID_KEYBOARD_BOOT HID_REPORT_KEYBOARD( HID_REPORT_ID(1), ), #endif -#if !CFG_TUD_DESC_BOOT_MOUSE +#if CFG_TUD_HID_MOUSE && !CFG_TUD_HID_MOUSE_BOOT HID_REPORT_MOUSE( HID_REPORT_ID(2), ) #endif @@ -309,7 +310,7 @@ typedef struct ATTR_PACKED #endif //------------- HID -------------// -#if CFG_TUD_HID_KEYBOARD && CFG_TUD_DESC_BOOT_KEYBOARD +#if CFG_TUD_HID_KEYBOARD && CFG_TUD_HID_KEYBOARD_BOOT struct ATTR_PACKED { tusb_desc_interface_t itf; @@ -318,7 +319,7 @@ typedef struct ATTR_PACKED } hid_kbd_boot; #endif -#if CFG_TUD_HID_MOUSE && CFG_TUD_DESC_BOOT_MOUSE +#if CFG_TUD_HID_MOUSE && CFG_TUD_HID_MOUSE_BOOT struct ATTR_PACKED { tusb_desc_interface_t itf; @@ -513,7 +514,7 @@ desc_auto_cfg_t const _desc_auto_config_struct = }, #endif // msc -#if CFG_TUD_HID_KEYBOARD && CFG_TUD_DESC_BOOT_KEYBOARD +#if CFG_TUD_HID_KEYBOARD && CFG_TUD_HID_KEYBOARD_BOOT .hid_kbd_boot = { .itf = @@ -553,7 +554,7 @@ desc_auto_cfg_t const _desc_auto_config_struct = #endif // boot keyboard //------------- HID Mouse -------------// -#if CFG_TUD_HID_MOUSE && CFG_TUD_DESC_BOOT_MOUSE +#if CFG_TUD_HID_MOUSE && CFG_TUD_HID_MOUSE_BOOT .hid_mse_boot = { .itf = diff --git a/src/tusb_option.h b/src/tusb_option.h index 4af327a5d..f4f1389da 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -171,9 +171,9 @@ #define CFG_TUD_MSC 0 #endif - // Generic (multiple) Report : Keyboard + Mouse + Gamepad + Joystick - #define TUD_OPT_HID_GENERIC (CFG_TUD_HID && ( (CFG_TUD_HID_KEYBOARD && !CFG_TUD_DESC_BOOT_KEYBOARD) || \ - (CFG_TUD_HID_MOUSE && !CFG_TUD_DESC_BOOT_MOUSE) )) + // IF HID Generic is required, it is multiple Report : Keyboard + Mouse + Gamepad + Joystick + #define TUD_OPT_HID_GENERIC ( (CFG_TUD_HID_KEYBOARD && !CFG_TUD_HID_KEYBOARD_BOOT) || \ + (CFG_TUD_HID_MOUSE && !CFG_TUD_HID_MOUSE_BOOT) ) #endif // TUSB_OPT_DEVICE_ENABLED @@ -206,7 +206,7 @@ //------------------------------------------------------------------ -// Config Verification +// Configuration Validation //------------------------------------------------------------------ #if (CFG_TUSB_OS != OPT_OS_NONE) && !defined (CFG_TUD_TASK_PRIO) -- cgit v1.3.1 From e07b1acbed02fff395c91b421b7fdf6c7cda61a4 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 13 Aug 2018 18:10:23 +0700 Subject: rename VERIFY to TU_VERIFY to avoid conflict with application --- examples/obsolete/host/src/cdc_serial_host_app.c | 2 +- examples/obsolete/host/src/keyboard_host_app.c | 2 +- examples/obsolete/host/src/mouse_host_app.c | 2 +- src/class/cdc/cdc.h | 6 +- src/class/cdc/cdc_device.c | 4 +- src/class/cdc/cdc_rndis.h | 4 +- src/class/cdc/cdc_rndis_host.c | 2 +- src/class/hid/hid_device.c | 12 ++-- src/class/hid/hid_host.c | 2 +- src/class/msc/msc.h | 32 ++++----- src/class/msc/msc_device.c | 2 +- src/class/msc/msc_device.h | 2 +- src/common/tusb_compiler.h | 6 +- src/common/tusb_types.h | 2 +- src/common/tusb_verify.h | 78 +++++++++++----------- src/device/usbd.c | 8 +-- src/host/ehci/ehci.c | 4 +- src/host/ehci/ehci.h | 10 +-- src/host/hub.h | 6 +- src/host/ohci/ohci.h | 10 +-- src/osal/osal.h | 8 +-- src/osal/osal_none.h | 8 +-- .../nxp/lpc11xx_lpc13xx/dcd_lpc_11uxx_13uxx.c | 2 +- src/portable/nxp/lpc17xx/dcd_lpc175x_6x.c | 6 +- src/portable/nxp/lpc17xx/dcd_lpc175x_6x.h | 2 +- src/portable/nxp/lpc43xx_lpc18xx/dcd_lpc43xx.c | 8 +-- src/portable/nxp/lpc43xx_lpc18xx/dcd_lpc43xx.h | 4 +- src/portable/nxp/lpc43xx_lpc18xx/hal_lpc43xx.c | 2 +- src/tusb.c | 2 +- 29 files changed, 119 insertions(+), 119 deletions(-) (limited to 'src/common') diff --git a/examples/obsolete/host/src/cdc_serial_host_app.c b/examples/obsolete/host/src/cdc_serial_host_app.c index 0782d0518..e21a3a67d 100644 --- a/examples/obsolete/host/src/cdc_serial_host_app.c +++ b/examples/obsolete/host/src/cdc_serial_host_app.c @@ -115,7 +115,7 @@ void cdc_serial_host_app_init(void) sem_hdl = osal_semaphore_create(1, 0); TU_ASSERT( sem_hdl, VOID_RETURN); - VERIFY( osal_task_create(cdc_serial_host_app_task, "cdc", 128, NULL, CDC_SERIAL_APP_TASK_PRIO), ); + TU_VERIFY( osal_task_create(cdc_serial_host_app_task, "cdc", 128, NULL, CDC_SERIAL_APP_TASK_PRIO), ); } //------------- main task -------------// diff --git a/examples/obsolete/host/src/keyboard_host_app.c b/examples/obsolete/host/src/keyboard_host_app.c index 130df0feb..26b1a0800 100644 --- a/examples/obsolete/host/src/keyboard_host_app.c +++ b/examples/obsolete/host/src/keyboard_host_app.c @@ -105,7 +105,7 @@ void keyboard_host_app_init(void) queue_kbd_hdl = osal_queue_create( QUEUE_KEYBOARD_REPORT_DEPTH, sizeof(hid_keyboard_report_t) ); TU_ASSERT( queue_kbd_hdl, VOID_RETURN ); - VERIFY( osal_task_create(keyboard_host_app_task, "kbd", 128, NULL, KEYBOARD_APP_TASK_PRIO), ); + TU_VERIFY( osal_task_create(keyboard_host_app_task, "kbd", 128, NULL, KEYBOARD_APP_TASK_PRIO), ); } //------------- main task -------------// diff --git a/examples/obsolete/host/src/mouse_host_app.c b/examples/obsolete/host/src/mouse_host_app.c index e9ee482d8..c326becb8 100644 --- a/examples/obsolete/host/src/mouse_host_app.c +++ b/examples/obsolete/host/src/mouse_host_app.c @@ -106,7 +106,7 @@ void mouse_host_app_init(void) queue_mouse_hdl = osal_queue_create( QUEUE_MOUSE_REPORT_DEPTH, sizeof(hid_mouse_report_t) ); TU_ASSERT( queue_mouse_hdl, VOID_RETURN); - VERIFY( osal_task_create(mouse_host_app_task, "mouse", 128, NULL, MOUSE_APP_TASK_PRIO), ); + TU_VERIFY( osal_task_create(mouse_host_app_task, "mouse", 128, NULL, MOUSE_APP_TASK_PRIO), ); } //------------- main task -------------// diff --git a/src/class/cdc/cdc.h b/src/class/cdc/cdc.h index b0c4f90d4..1b127ad28 100644 --- a/src/class/cdc/cdc.h +++ b/src/class/cdc/cdc.h @@ -300,7 +300,7 @@ typedef struct ATTR_PACKED uint8_t : 0; }cdc_acm_capability_t; -VERIFY_STATIC(sizeof(cdc_acm_capability_t) == 1, "mostly problem with compiler"); +TU_VERIFY_STATIC(sizeof(cdc_acm_capability_t) == 1, "mostly problem with compiler"); /// \brief Abstract Control Management Functional Descriptor /// \details This functional descriptor describes the commands supported by by the Communications Class interface with SubClass code of \ref CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL @@ -390,7 +390,7 @@ typedef struct ATTR_PACKED uint8_t data_bits; ///< can be 5, 6, 7, 8 or 16 } cdc_line_coding_t; -VERIFY_STATIC(sizeof(cdc_line_coding_t) == 7, "size is not correct"); +TU_VERIFY_STATIC(sizeof(cdc_line_coding_t) == 7, "size is not correct"); typedef struct ATTR_PACKED { @@ -399,7 +399,7 @@ typedef struct ATTR_PACKED uint16_t : 14; } cdc_line_control_state_t; -VERIFY_STATIC(sizeof(cdc_line_control_state_t) == 2, "size is not correct"); +TU_VERIFY_STATIC(sizeof(cdc_line_control_state_t) == 2, "size is not correct"); /** @} */ diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index bbf1c8ceb..175e78d2f 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -157,11 +157,11 @@ uint32_t tud_cdc_n_write(uint8_t itf, void const* buffer, uint32_t bufsize) bool tud_cdc_n_write_flush (uint8_t itf) { cdcd_interface_t* p_cdc = &_cdcd_itf[itf]; - VERIFY( !dcd_edpt_busy(TUD_OPT_RHPORT, p_cdc->ep_in) ); // skip if previous transfer not complete + TU_VERIFY( !dcd_edpt_busy(TUD_OPT_RHPORT, p_cdc->ep_in) ); // skip if previous transfer not complete uint16_t count = tu_fifo_read_n(&_cdcd_itf[itf].tx_ff, p_cdc->epout_buf, CFG_TUD_CDC_EPSIZE); - VERIFY( tud_cdc_n_connected(itf) ); // fifo is empty if not connected + TU_VERIFY( tud_cdc_n_connected(itf) ); // fifo is empty if not connected if ( count ) TU_ASSERT( dcd_edpt_xfer(TUD_OPT_RHPORT, p_cdc->ep_in, p_cdc->epout_buf, count) ); diff --git a/src/class/cdc/cdc_rndis.h b/src/class/cdc/cdc_rndis.h index 460477eb0..20da5660b 100644 --- a/src/class/cdc/cdc_rndis.h +++ b/src/class/cdc/cdc_rndis.h @@ -142,7 +142,7 @@ typedef struct { uint8_t oid_buffer[] ; ///< Flexible array contains the input data supplied by the host, required for the OID query request processing by the device, as per the host NDIS specification. } rndis_msg_query_t, rndis_msg_set_t; -VERIFY_STATIC(sizeof(rndis_msg_query_t) == 28, "Make sure flexible array member does not affect layout"); +TU_VERIFY_STATIC(sizeof(rndis_msg_query_t) == 28, "Make sure flexible array member does not affect layout"); /// \brief Query Complete Message /// \details This message MUST be sent by the device in response to a query OID message. @@ -156,7 +156,7 @@ typedef struct { uint8_t oid_buffer[] ; ///< Flexible array member contains the response data to the OID query request as specified by the host. } rndis_msg_query_cmplt_t; -VERIFY_STATIC(sizeof(rndis_msg_query_cmplt_t) == 24, "Make sure flexible array member does not affect layout"); +TU_VERIFY_STATIC(sizeof(rndis_msg_query_cmplt_t) == 24, "Make sure flexible array member does not affect layout"); //------------- Reset -------------// /// \brief Reset Message diff --git a/src/class/cdc/cdc_rndis_host.c b/src/class/cdc/cdc_rndis_host.c index 62361feb4..4d28b0e0c 100644 --- a/src/class/cdc/cdc_rndis_host.c +++ b/src/class/cdc/cdc_rndis_host.c @@ -75,7 +75,7 @@ static tusb_error_t send_message_get_response_subtask( uint8_t dev_addr, cdch_da tusb_error_t tusbh_cdc_rndis_get_mac_addr(uint8_t dev_addr, uint8_t mac_address[6]) { TU_ASSERT( tusbh_cdc_rndis_is_mounted(dev_addr), TUSB_ERROR_CDCH_DEVICE_NOT_MOUNTED); - VERIFY( mac_address, TUSB_ERROR_INVALID_PARA); + TU_VERIFY( mac_address, TUSB_ERROR_INVALID_PARA); memcpy(mac_address, rndish_data[dev_addr-1].mac_address, 6); diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index 0527c14bf..410359e6d 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -125,7 +125,7 @@ bool tud_hid_generic_ready(void) bool tud_hid_generic_report(uint8_t report_id, void const* report, uint8_t len) { - VERIFY( tud_hid_generic_ready() && (len < REPORT_BUFSIZE) ); + TU_VERIFY( tud_hid_generic_ready() && (len < REPORT_BUFSIZE) ); hidd_interface_t * p_hid = &_hidd_itf[ITF_IDX_GENERIC]; @@ -159,7 +159,7 @@ bool tud_hid_keyboard_is_boot_protocol(void) static bool hidd_kbd_report(hid_keyboard_report_t const *p_report) { - VERIFY( tud_hid_keyboard_ready() ); + TU_VERIFY( tud_hid_keyboard_ready() ); hidd_interface_t * p_hid = _kbd_rpt.itf; @@ -253,7 +253,7 @@ bool tud_hid_mouse_is_boot_protocol(void) static bool hidd_mouse_report(hid_mouse_report_t const *p_report) { - VERIFY( tud_hid_mouse_ready() ); + TU_VERIFY( tud_hid_mouse_ready() ); hidd_interface_t * p_hid = _mse_rpt.itf; memcpy(p_hid->report_buf, p_report, sizeof(hid_mouse_report_t)); @@ -277,7 +277,7 @@ bool tud_hid_mouse_data(uint8_t buttons, int8_t x, int8_t y, int8_t scroll, int8 bool tud_hid_mouse_move(int8_t x, int8_t y) { - VERIFY( tud_hid_mouse_ready() ); + TU_VERIFY( tud_hid_mouse_ready() ); hidd_interface_t * p_hid = _mse_rpt.itf; uint8_t prev_buttons = p_hid->report_buf[0]; @@ -287,7 +287,7 @@ bool tud_hid_mouse_move(int8_t x, int8_t y) bool tud_hid_mouse_scroll(int8_t vertical, int8_t horizontal) { - VERIFY( tud_hid_mouse_ready() ); + TU_VERIFY( tud_hid_mouse_ready() ); hidd_interface_t * p_hid = _mse_rpt.itf; uint8_t prev_buttons = p_hid->report_buf[0]; @@ -390,7 +390,7 @@ tusb_error_t hidd_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, u TU_ASSERT(p_hid, ERR_TUD_INVALID_DESCRIPTOR); } - VERIFY(p_hid->desc_report, ERR_TUD_INVALID_DESCRIPTOR); + TU_VERIFY(p_hid->desc_report, ERR_TUD_INVALID_DESCRIPTOR); TU_ASSERT( dcd_edpt_open(rhport, desc_edpt), ERR_TUD_EDPT_OPEN_FAILED ); p_hid->itf_num = desc_itf->bInterfaceNumber; diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index fa617c5b0..369dad638 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -77,7 +77,7 @@ tusb_error_t hidh_interface_get_report(uint8_t dev_addr, void * report, hidh_int //------------- parameters validation -------------// // TODO change to use is configured function TU_ASSERT (TUSB_DEVICE_STATE_CONFIGURED == tuh_device_get_state(dev_addr), TUSB_ERROR_DEVICE_NOT_READY); - VERIFY (report, TUSB_ERROR_INVALID_PARA); + TU_VERIFY (report, TUSB_ERROR_INVALID_PARA); TU_ASSSERT (!hcd_pipe_is_busy(p_hid->pipe_hdl), TUSB_ERROR_INTERFACE_IS_BUSY); TU_ASSERT_ERR( hcd_pipe_xfer(p_hid->pipe_hdl, report, p_hid->report_size, true) ) ; diff --git a/src/class/msc/msc.h b/src/class/msc/msc.h index ab8f066b3..ca5615055 100644 --- a/src/class/msc/msc.h +++ b/src/class/msc/msc.h @@ -109,7 +109,7 @@ typedef struct ATTR_PACKED uint8_t command[16] ; ///< The command block to be executed by the device. The device shall interpret the first cmd_len bytes in this field as a command block }msc_cbw_t; -VERIFY_STATIC(sizeof(msc_cbw_t) == 31, "size is not correct"); +TU_VERIFY_STATIC(sizeof(msc_cbw_t) == 31, "size is not correct"); /// Command Status Wrapper typedef struct ATTR_PACKED @@ -120,7 +120,7 @@ typedef struct ATTR_PACKED uint8_t status ; ///< indicates the success or failure of the command. Values from \ref msc_csw_status_t }msc_csw_t; -VERIFY_STATIC(sizeof(msc_csw_t) == 13, "size is not correct"); +TU_VERIFY_STATIC(sizeof(msc_csw_t) == 13, "size is not correct"); //--------------------------------------------------------------------+ // SCSI Constant @@ -173,7 +173,7 @@ typedef struct ATTR_PACKED uint8_t control ; } scsi_test_unit_ready_t; -VERIFY_STATIC(sizeof(scsi_test_unit_ready_t) == 6, "size is not correct"); +TU_VERIFY_STATIC(sizeof(scsi_test_unit_ready_t) == 6, "size is not correct"); /// SCSI Inquiry Command typedef struct ATTR_PACKED @@ -186,7 +186,7 @@ typedef struct ATTR_PACKED uint8_t control ; } scsi_inquiry_t, scsi_request_sense_t; -VERIFY_STATIC(sizeof(scsi_inquiry_t) == 6, "size is not correct"); +TU_VERIFY_STATIC(sizeof(scsi_inquiry_t) == 6, "size is not correct"); /// SCSI Inquiry Response Data typedef struct ATTR_PACKED @@ -232,7 +232,7 @@ typedef struct ATTR_PACKED uint8_t product_rev[4]; ///< 4 bytes of ASCII data defined by the vendor. } scsi_inquiry_resp_t; -VERIFY_STATIC(sizeof(scsi_inquiry_resp_t) == 36, "size is not correct"); +TU_VERIFY_STATIC(sizeof(scsi_inquiry_resp_t) == 36, "size is not correct"); typedef struct ATTR_PACKED @@ -259,7 +259,7 @@ typedef struct ATTR_PACKED } scsi_sense_fixed_resp_t; -VERIFY_STATIC(sizeof(scsi_sense_fixed_resp_t) == 18, "size is not correct"); +TU_VERIFY_STATIC(sizeof(scsi_sense_fixed_resp_t) == 18, "size is not correct"); typedef struct ATTR_PACKED { @@ -277,7 +277,7 @@ typedef struct ATTR_PACKED uint8_t control; } scsi_mode_sense6_t; -VERIFY_STATIC( sizeof(scsi_mode_sense6_t) == 6, "size is not correct"); +TU_VERIFY_STATIC( sizeof(scsi_mode_sense6_t) == 6, "size is not correct"); typedef struct ATTR_PACKED { @@ -287,7 +287,7 @@ typedef struct ATTR_PACKED uint8_t block_descriptor_len; } scsi_mode_sense6_resp_t; -VERIFY_STATIC( sizeof(scsi_mode_sense6_resp_t) == 4, "size is not correct"); +TU_VERIFY_STATIC( sizeof(scsi_mode_sense6_resp_t) == 4, "size is not correct"); typedef struct ATTR_PACKED { @@ -297,7 +297,7 @@ typedef struct ATTR_PACKED uint8_t control; } scsi_prevent_allow_medium_removal_t; -VERIFY_STATIC( sizeof(scsi_prevent_allow_medium_removal_t) == 6, "size is not correct"); +TU_VERIFY_STATIC( sizeof(scsi_prevent_allow_medium_removal_t) == 6, "size is not correct"); typedef struct ATTR_PACKED { @@ -320,7 +320,7 @@ typedef struct ATTR_PACKED uint8_t control; } scsi_start_stop_unit_t; -VERIFY_STATIC( sizeof(scsi_start_stop_unit_t) == 6, "size is not correct"); +TU_VERIFY_STATIC( sizeof(scsi_start_stop_unit_t) == 6, "size is not correct"); //--------------------------------------------------------------------+ // SCSI MMC @@ -334,7 +334,7 @@ typedef struct ATTR_PACKED uint8_t control; } scsi_read_format_capacity_t; -VERIFY_STATIC( sizeof(scsi_read_format_capacity_t) == 10, "size is not correct"); +TU_VERIFY_STATIC( sizeof(scsi_read_format_capacity_t) == 10, "size is not correct"); typedef struct ATTR_PACKED{ uint8_t reserved[3]; @@ -348,7 +348,7 @@ typedef struct ATTR_PACKED{ } scsi_read_format_capacity_data_t; -VERIFY_STATIC( sizeof(scsi_read_format_capacity_data_t) == 12, "size is not correct"); +TU_VERIFY_STATIC( sizeof(scsi_read_format_capacity_data_t) == 12, "size is not correct"); //--------------------------------------------------------------------+ // SCSI Block Command (SBC-3) @@ -366,7 +366,7 @@ typedef struct ATTR_PACKED uint8_t control ; } scsi_read_capacity10_t; -VERIFY_STATIC(sizeof(scsi_read_capacity10_t) == 10, "size is not correct"); +TU_VERIFY_STATIC(sizeof(scsi_read_capacity10_t) == 10, "size is not correct"); /// SCSI Read Capacity 10 Response Data typedef struct { @@ -374,7 +374,7 @@ typedef struct { uint32_t block_size ; ///< Block size in bytes } scsi_read_capacity10_resp_t; -VERIFY_STATIC(sizeof(scsi_read_capacity10_resp_t) == 8, "size is not correct"); +TU_VERIFY_STATIC(sizeof(scsi_read_capacity10_resp_t) == 8, "size is not correct"); /// SCSI Read 10 Command typedef struct ATTR_PACKED @@ -387,8 +387,8 @@ typedef struct ATTR_PACKED uint8_t control ; } scsi_read10_t, scsi_write10_t; -VERIFY_STATIC(sizeof(scsi_read10_t) == 10, "size is not correct"); -VERIFY_STATIC(sizeof(scsi_write10_t) == 10, "size is not correct"); +TU_VERIFY_STATIC(sizeof(scsi_read10_t) == 10, "size is not correct"); +TU_VERIFY_STATIC(sizeof(scsi_write10_t) == 10, "size is not correct"); #ifdef __cplusplus } diff --git a/src/class/msc/msc_device.c b/src/class/msc/msc_device.c index 27762805c..a11212c4b 100644 --- a/src/class/msc/msc_device.c +++ b/src/class/msc/msc_device.c @@ -152,7 +152,7 @@ void mscd_reset(uint8_t rhport) tusb_error_t mscd_open(uint8_t rhport, tusb_desc_interface_t const * p_desc_itf, uint16_t *p_len) { // only support SCSI's BOT protocol - VERIFY( ( MSC_SUBCLASS_SCSI == p_desc_itf->bInterfaceSubClass && + TU_VERIFY( ( MSC_SUBCLASS_SCSI == p_desc_itf->bInterfaceSubClass && MSC_PROTOCOL_BOT == p_desc_itf->bInterfaceProtocol ), TUSB_ERROR_MSC_UNSUPPORTED_PROTOCOL ); mscd_interface_t * p_msc = &_mscd_itf; diff --git a/src/class/msc/msc_device.h b/src/class/msc/msc_device.h index 6080b10df..8403dfed9 100644 --- a/src/class/msc/msc_device.h +++ b/src/class/msc/msc_device.h @@ -47,7 +47,7 @@ //--------------------------------------------------------------------+ // Class Driver Configuration //--------------------------------------------------------------------+ -VERIFY_STATIC(CFG_TUD_MSC_BUFSIZE < UINT16_MAX, "Size is not correct"); +TU_VERIFY_STATIC(CFG_TUD_MSC_BUFSIZE < UINT16_MAX, "Size is not correct"); #ifndef CFG_TUD_MSC_MAXLUN #define CFG_TUD_MSC_MAXLUN 1 diff --git a/src/common/tusb_compiler.h b/src/common/tusb_compiler.h index 35a4cc928..09cc59633 100644 --- a/src/common/tusb_compiler.h +++ b/src/common/tusb_compiler.h @@ -56,12 +56,12 @@ #endif //--------------------------------------------------------------------+ -// Compile-time Assert (use VERIFY_STATIC to avoid name conflict) +// Compile-time Assert (use TU_VERIFY_STATIC to avoid name conflict) //--------------------------------------------------------------------+ #if defined(__ICCARM__) || (__STDC_VERSION__ >= 201112L ) - #define VERIFY_STATIC static_assert + #define TU_VERIFY_STATIC static_assert #else - #define VERIFY_STATIC(const_expr, _mess) enum { XSTRING_CONCAT_(_verify_static_, _TU_COUNTER_) = 1/(!!(const_expr)) } + #define TU_VERIFY_STATIC(const_expr, _mess) enum { XSTRING_CONCAT_(_verify_static_, _TU_COUNTER_) = 1/(!!(const_expr)) } #endif // allow debugger to watch any module-wide variables anywhere diff --git a/src/common/tusb_types.h b/src/common/tusb_types.h index 1e8a5ef27..c3ed4f2bd 100644 --- a/src/common/tusb_types.h +++ b/src/common/tusb_types.h @@ -369,7 +369,7 @@ typedef struct ATTR_PACKED{ uint16_t wLength; } tusb_control_request_t; -VERIFY_STATIC( sizeof(tusb_control_request_t) == 8, "mostly compiler option issue"); +TU_VERIFY_STATIC( sizeof(tusb_control_request_t) == 8, "mostly compiler option issue"); // TODO move to somewhere suitable static inline uint8_t bm_request_type(uint8_t direction, uint8_t type, uint8_t recipient) diff --git a/src/common/tusb_verify.h b/src/common/tusb_verify.h index adcdfc97f..41c2b5be1 100644 --- a/src/common/tusb_verify.h +++ b/src/common/tusb_verify.h @@ -50,8 +50,8 @@ * * e.g * - * - VERIFY( cond ) will return false if cond is false - * - VERIFY( cond, err) will return err instead if cond is false + * - TU_VERIFY( cond ) will return false if cond is false + * - TU_VERIFY( cond, err) will return err instead if cond is false *------------------------------------------------------------------*/ #ifdef __cplusplus @@ -60,7 +60,7 @@ //--------------------------------------------------------------------+ -// VERIFY Helper +// TU_VERIFY Helper //--------------------------------------------------------------------+ #if CFG_TUSB_DEBUG >= 1 #include @@ -88,21 +88,21 @@ /* Macro Generator *------------------------------------------------------------------*/ -// Helper to implement optional parameter for VERIFY Macro family +// Helper to implement optional parameter for TU_VERIFY Macro family #define GET_3RD_ARG(arg1, arg2, arg3, ...) arg3 #define GET_4TH_ARG(arg1, arg2, arg3, arg4, ...) arg4 -/*------------- Generator for VERIFY and VERIFY_HDLR -------------*/ -#define VERIFY_DEFINE(_cond, _handler, _ret) do { if ( !(_cond) ) { _handler; return _ret; } } while(0) +/*------------- Generator for TU_VERIFY and TU_VERIFY_HDLR -------------*/ +#define TU_VERIFY_DEFINE(_cond, _handler, _ret) do { if ( !(_cond) ) { _handler; return _ret; } } while(0) -/*------------- Generator for VERIFY_ERR and VERIFY_ERR_HDLR -------------*/ -#define VERIFY_ERR_DEF2(_error, _handler) \ +/*------------- Generator for TU_VERIFY_ERR and TU_VERIFY_ERR_HDLR -------------*/ +#define TU_VERIFY_ERR_DEF2(_error, _handler) \ do { \ uint32_t _err = (uint32_t)(_error); \ if ( 0 != _err ) { _MESS_ERR(_err); _handler; return _err; }\ } while(0) -#define VERIFY_ERR_DEF3(_error, _handler, _ret) \ +#define TU_VERIFY_ERR_DEF3(_error, _handler, _ret) \ do { \ uint32_t _err = (uint32_t)(_error); \ if ( 0 != _err ) { _MESS_ERR(_err); _handler; return _ret; }\ @@ -112,66 +112,66 @@ /*------------------------------------------------------------------*/ -/* VERIFY - * - VERIFY_1ARGS : return false if failed - * - VERIFY_2ARGS : return provided value if failed +/* TU_VERIFY + * - TU_VERIFY_1ARGS : return false if failed + * - TU_VERIFY_2ARGS : return provided value if failed *------------------------------------------------------------------*/ -#define VERIFY_1ARGS(_cond) VERIFY_DEFINE(_cond, , false) -#define VERIFY_2ARGS(_cond, _ret) VERIFY_DEFINE(_cond, , _ret) +#define TU_VERIFY_1ARGS(_cond) TU_VERIFY_DEFINE(_cond, , false) +#define TU_VERIFY_2ARGS(_cond, _ret) TU_VERIFY_DEFINE(_cond, , _ret) -#define VERIFY(...) GET_3RD_ARG(__VA_ARGS__, VERIFY_2ARGS, VERIFY_1ARGS)(__VA_ARGS__) +#define TU_VERIFY(...) GET_3RD_ARG(__VA_ARGS__, TU_VERIFY_2ARGS, TU_VERIFY_1ARGS)(__VA_ARGS__) /*------------------------------------------------------------------*/ -/* VERIFY WITH HANDLER - * - VERIFY_HDLR_2ARGS : execute handler, return false if failed - * - VERIFY_HDLR_3ARGS : execute handler, return provided error if failed +/* TU_VERIFY WITH HANDLER + * - TU_VERIFY_HDLR_2ARGS : execute handler, return false if failed + * - TU_VERIFY_HDLR_3ARGS : execute handler, return provided error if failed *------------------------------------------------------------------*/ -#define VERIFY_HDLR_2ARGS(_cond, _handler) VERIFY_DEFINE(_cond, _handler, false) -#define VERIFY_HDLR_3ARGS(_cond, _handler, _ret) VERIFY_DEFINE(_cond, _handler, _ret) +#define TU_VERIFY_HDLR_2ARGS(_cond, _handler) TU_VERIFY_DEFINE(_cond, _handler, false) +#define TU_VERIFY_HDLR_3ARGS(_cond, _handler, _ret) TU_VERIFY_DEFINE(_cond, _handler, _ret) -#define VERIFY_HDLR(...) GET_4TH_ARG(__VA_ARGS__, VERIFY_HDLR_3ARGS, VERIFY_HDLR_2ARGS)(__VA_ARGS__) +#define TU_VERIFY_HDLR(...) GET_4TH_ARG(__VA_ARGS__, TU_VERIFY_HDLR_3ARGS, TU_VERIFY_HDLR_2ARGS)(__VA_ARGS__) /*------------------------------------------------------------------*/ -/* VERIFY STATUS - * - VERIFY_ERR_1ARGS : return status of condition if failed - * - VERIFY_ERR_2ARGS : return provided status code if failed +/* TU_VERIFY STATUS + * - TU_VERIFY_ERR_1ARGS : return status of condition if failed + * - TU_VERIFY_ERR_2ARGS : return provided status code if failed *------------------------------------------------------------------*/ -#define VERIFY_ERR_1ARGS(_error) VERIFY_ERR_DEF2(_error, ) -#define VERIFY_ERR_2ARGS(_error, _ret) VERIFY_ERR_DEF3(_error, ,_ret) +#define TU_VERIFY_ERR_1ARGS(_error) TU_VERIFY_ERR_DEF2(_error, ) +#define TU_VERIFY_ERR_2ARGS(_error, _ret) TU_VERIFY_ERR_DEF3(_error, ,_ret) -#define VERIFY_ERR(...) GET_3RD_ARG(__VA_ARGS__, VERIFY_ERR_2ARGS, VERIFY_ERR_1ARGS)(__VA_ARGS__) +#define TU_VERIFY_ERR(...) GET_3RD_ARG(__VA_ARGS__, TU_VERIFY_ERR_2ARGS, TU_VERIFY_ERR_1ARGS)(__VA_ARGS__) /*------------------------------------------------------------------*/ -/* VERIFY STATUS WITH HANDLER - * - VERIFY_ERR_HDLR_2ARGS : execute handler, return status if failed - * - VERIFY_ERR_HDLR_3ARGS : execute handler, return provided error if failed +/* TU_VERIFY STATUS WITH HANDLER + * - TU_VERIFY_ERR_HDLR_2ARGS : execute handler, return status if failed + * - TU_VERIFY_ERR_HDLR_3ARGS : execute handler, return provided error if failed *------------------------------------------------------------------*/ -#define VERIFY_ERR_HDLR_2ARGS(_error, _handler) VERIFY_ERR_DEF2(_error, _handler) -#define VERIFY_ERR_HDLR_3ARGS(_error, _handler, _ret) VERIFY_ERR_DEF3(_error, _handler, _ret) +#define TU_VERIFY_ERR_HDLR_2ARGS(_error, _handler) TU_VERIFY_ERR_DEF2(_error, _handler) +#define TU_VERIFY_ERR_HDLR_3ARGS(_error, _handler, _ret) TU_VERIFY_ERR_DEF3(_error, _handler, _ret) -#define VERIFY_ERR_HDLR(...) GET_4TH_ARG(__VA_ARGS__, VERIFY_ERR_HDLR_3ARGS, VERIFY_ERR_HDLR_2ARGS)(__VA_ARGS__) +#define TU_VERIFY_ERR_HDLR(...) GET_4TH_ARG(__VA_ARGS__, TU_VERIFY_ERR_HDLR_3ARGS, TU_VERIFY_ERR_HDLR_2ARGS)(__VA_ARGS__) /*------------------------------------------------------------------*/ /* ASSERT - * basically VERIFY with verify_breakpoint() as handler + * basically TU_VERIFY with verify_breakpoint() as handler * - 1 arg : return false if failed * - 2 arg : return error if failed *------------------------------------------------------------------*/ -#define ASSERT_1ARGS(_cond) VERIFY_DEFINE(_cond, _MESS_FAILED(); verify_breakpoint(), false) -#define ASSERT_2ARGS(_cond, _ret) VERIFY_DEFINE(_cond, _MESS_FAILED(); verify_breakpoint(), _ret) +#define ASSERT_1ARGS(_cond) TU_VERIFY_DEFINE(_cond, _MESS_FAILED(); verify_breakpoint(), false) +#define ASSERT_2ARGS(_cond, _ret) TU_VERIFY_DEFINE(_cond, _MESS_FAILED(); verify_breakpoint(), _ret) #define TU_ASSERT(...) GET_3RD_ARG(__VA_ARGS__, ASSERT_2ARGS, ASSERT_1ARGS)(__VA_ARGS__) /*------------------------------------------------------------------*/ /* ASSERT Error - * basically VERIFY Error with verify_breakpoint() as handler + * basically TU_VERIFY Error with verify_breakpoint() as handler *------------------------------------------------------------------*/ -#define ASERT_ERR_1ARGS(_error) VERIFY_ERR_DEF2(_error, verify_breakpoint()) -#define ASERT_ERR_2ARGS(_error, _ret) VERIFY_ERR_DEF3(_error, verify_breakpoint(), _ret) +#define ASERT_ERR_1ARGS(_error) TU_VERIFY_ERR_DEF2(_error, verify_breakpoint()) +#define ASERT_ERR_2ARGS(_error, _ret) TU_VERIFY_ERR_DEF3(_error, verify_breakpoint(), _ret) #define TU_ASSERT_ERR(...) GET_3RD_ARG(__VA_ARGS__, ASERT_ERR_2ARGS, ASERT_ERR_1ARGS)(__VA_ARGS__) diff --git a/src/device/usbd.c b/src/device/usbd.c index 219562fa6..79ad8ffa2 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -189,7 +189,7 @@ typedef struct ATTR_ALIGNED(4) }; } usbd_task_event_t; -VERIFY_STATIC(sizeof(usbd_task_event_t) <= 12, "size is not correct"); +TU_VERIFY_STATIC(sizeof(usbd_task_event_t) <= 12, "size is not correct"); OSAL_TASK_DEF(_usbd_task_def, "usbd", usbd_task, CFG_TUD_TASK_PRIO, CFG_TUD_TASK_STACK_SZ); @@ -234,10 +234,10 @@ tusb_error_t usbd_init (void) //------------- Task init -------------// _usbd_q = osal_queue_create(&_usbd_qdef); - VERIFY(_usbd_q, TUSB_ERROR_OSAL_QUEUE_FAILED); + TU_VERIFY(_usbd_q, TUSB_ERROR_OSAL_QUEUE_FAILED); _usbd_ctrl_sem = osal_semaphore_create(&_usbd_sem_def); - VERIFY(_usbd_q, TUSB_ERROR_OSAL_SEMAPHORE_FAILED); + TU_VERIFY(_usbd_q, TUSB_ERROR_OSAL_SEMAPHORE_FAILED); osal_task_create(&_usbd_task_def); @@ -507,7 +507,7 @@ static uint16_t get_descriptor(uint8_t rhport, tusb_control_request_t const * co if ( desc_index < tud_desc_set.string_count ) { desc_data = tud_desc_set.string_arr[desc_index]; - VERIFY( desc_data != NULL, 0 ); + TU_VERIFY( desc_data != NULL, 0 ); len = desc_data[0]; // first byte of descriptor is its size }else diff --git a/src/host/ehci/ehci.c b/src/host/ehci/ehci.c index 09f2f573a..32fcc8140 100644 --- a/src/host/ehci/ehci.c +++ b/src/host/ehci/ehci.c @@ -64,7 +64,7 @@ CFG_TUSB_ATTR_USBRAM STATIC_VAR ehci_data_t ehci_data; CFG_TUSB_ATTR_USBRAM ATTR_ALIGNED(4096) STATIC_VAR ehci_link_t period_frame_list0[EHCI_FRAMELIST_SIZE]; #ifndef __ICCARM__ // IAR cannot able to determine the alignment with datalignment pragma - VERIFY_STATIC( ALIGN_OF(period_frame_list0) == 4096, "Period Framelist must be 4k alginment"); // validation + TU_VERIFY_STATIC( ALIGN_OF(period_frame_list0) == 4096, "Period Framelist must be 4k alginment"); // validation #endif #endif @@ -72,7 +72,7 @@ CFG_TUSB_ATTR_USBRAM STATIC_VAR ehci_data_t ehci_data; CFG_TUSB_ATTR_USBRAM ATTR_ALIGNED(4096) STATIC_VAR ehci_link_t period_frame_list1[EHCI_FRAMELIST_SIZE]; #ifndef __ICCARM__ // IAR cannot able to determine the alignment with datalignment pragma - VERIFY_STATIC( ALIGN_OF(period_frame_list1) == 4096, "Period Framelist must be 4k alginment"); // validation + TU_VERIFY_STATIC( ALIGN_OF(period_frame_list1) == 4096, "Period Framelist must be 4k alginment"); // validation #endif #endif #endif diff --git a/src/host/ehci/ehci.h b/src/host/ehci/ehci.h index 250023ee5..f5180402b 100644 --- a/src/host/ehci/ehci.h +++ b/src/host/ehci/ehci.h @@ -81,7 +81,7 @@ enum { }; //------------- Validation -------------// -VERIFY_STATIC(EHCI_CFG_FRAMELIST_SIZE_BITS <= 7, "incorrect value"); +TU_VERIFY_STATIC(EHCI_CFG_FRAMELIST_SIZE_BITS <= 7, "incorrect value"); //--------------------------------------------------------------------+ // EHCI Data Structure @@ -150,7 +150,7 @@ typedef struct { uint32_t buffer[5]; } ehci_qtd_t; // XXX qtd is used to declare overlay in ehci_qhd_t -> cannot be declared with ATTR_ALIGNED(32) -VERIFY_STATIC( sizeof(ehci_qtd_t) == 32, "size is not correct" ); +TU_VERIFY_STATIC( sizeof(ehci_qtd_t) == 32, "size is not correct" ); /// Queue Head (section 3.6) typedef struct ATTR_ALIGNED(32) { @@ -202,7 +202,7 @@ typedef struct ATTR_ALIGNED(32) { ehci_qtd_t * volatile p_qtd_list_tail; // tail of the scheduled TD list } ehci_qhd_t; -VERIFY_STATIC( sizeof(ehci_qhd_t) == 64, "size is not correct" ); +TU_VERIFY_STATIC( sizeof(ehci_qhd_t) == 64, "size is not correct" ); /// Highspeed Isochronous Transfer Descriptor (section 3.3) typedef struct ATTR_ALIGNED(32) { @@ -234,7 +234,7 @@ typedef struct ATTR_ALIGNED(32) { // uint32_t reserved[6]; } ehci_itd_t; -VERIFY_STATIC( sizeof(ehci_itd_t) == 64, "size is not correct" ); +TU_VERIFY_STATIC( sizeof(ehci_itd_t) == 64, "size is not correct" ); /// Split (Full-Speed) Isochronous Transfer Descriptor typedef struct ATTR_ALIGNED(32) { @@ -298,7 +298,7 @@ typedef struct ATTR_ALIGNED(32) { uint8_t reserved2[2]; } ehci_sitd_t; -VERIFY_STATIC( sizeof(ehci_sitd_t) == 32, "size is not correct" ); +TU_VERIFY_STATIC( sizeof(ehci_sitd_t) == 32, "size is not correct" ); //--------------------------------------------------------------------+ // EHCI Operational Register diff --git a/src/host/hub.h b/src/host/hub.h index b8499275c..67c02f2e3 100644 --- a/src/host/hub.h +++ b/src/host/hub.h @@ -104,7 +104,7 @@ typedef struct ATTR_PACKED{ uint8_t PortPwrCtrlMask; // just for compatibility, should be 0xff } descriptor_hub_desc_t; -VERIFY_STATIC( sizeof(descriptor_hub_desc_t) == 9, "size is not correct"); +TU_VERIFY_STATIC( sizeof(descriptor_hub_desc_t) == 9, "size is not correct"); enum { HUB_REQUEST_GET_STATUS = 0 , @@ -157,7 +157,7 @@ typedef struct { } status, status_change; } hub_status_response_t; -VERIFY_STATIC( sizeof(hub_status_response_t) == 4, "size is not correct"); +TU_VERIFY_STATIC( sizeof(hub_status_response_t) == 4, "size is not correct"); // data in response of HUB_REQUEST_GET_STATUS, wIndex = Port num typedef struct { @@ -182,7 +182,7 @@ typedef struct { } status_current, status_change; } hub_port_status_response_t; -VERIFY_STATIC( sizeof(hub_port_status_response_t) == 4, "size is not correct"); +TU_VERIFY_STATIC( sizeof(hub_port_status_response_t) == 4, "size is not correct"); tusb_error_t hub_port_reset_subtask(uint8_t hub_addr, uint8_t hub_port); tusb_error_t hub_port_clear_feature_subtask(uint8_t hub_addr, uint8_t hub_port, uint8_t feature); diff --git a/src/host/ohci/ohci.h b/src/host/ohci/ohci.h index f49d85261..c407b8ac1 100644 --- a/src/host/ohci/ohci.h +++ b/src/host/ohci/ohci.h @@ -79,7 +79,7 @@ typedef struct { uint8_t reserved[116+4]; // TODO try to make use of this area if possible, extra 4 byte to make the whole struct size = 256 }ohci_hcca_t; // ATTR_ALIGNED(256) -VERIFY_STATIC( sizeof(ohci_hcca_t) == 256, "size is not correct" ); +TU_VERIFY_STATIC( sizeof(ohci_hcca_t) == 256, "size is not correct" ); typedef struct { uint32_t reserved[2]; @@ -112,7 +112,7 @@ typedef struct ATTR_ALIGNED(16) { uint8_t* buffer_end; } ohci_gtd_t; -VERIFY_STATIC( sizeof(ohci_gtd_t) == 16, "size is not correct" ); +TU_VERIFY_STATIC( sizeof(ohci_gtd_t) == 16, "size is not correct" ); typedef struct ATTR_ALIGNED(16) { //------------- Word 0 -------------// @@ -153,7 +153,7 @@ typedef struct ATTR_ALIGNED(16) { uint32_t next_ed; // 4 lsb bits are free to use } ohci_ed_t; -VERIFY_STATIC( sizeof(ohci_ed_t) == 16, "size is not correct" ); +TU_VERIFY_STATIC( sizeof(ohci_ed_t) == 16, "size is not correct" ); typedef struct ATTR_ALIGNED(32) { /*---------- Word 1 ----------*/ @@ -178,7 +178,7 @@ typedef struct ATTR_ALIGNED(32) { volatile uint16_t offset_packetstatus[8]; } ochi_itd_t; -VERIFY_STATIC( sizeof(ochi_itd_t) == 32, "size is not correct" ); +TU_VERIFY_STATIC( sizeof(ochi_itd_t) == 32, "size is not correct" ); // structure with member alignment required from large to small typedef struct ATTR_ALIGNED(256) { @@ -298,7 +298,7 @@ typedef volatile struct }; }ohci_registers_t; -VERIFY_STATIC( sizeof(ohci_registers_t) == 0x5c, "size is not correct"); +TU_VERIFY_STATIC( sizeof(ohci_registers_t) == 0x5c, "size is not correct"); #ifdef __cplusplus } diff --git a/src/osal/osal.h b/src/osal/osal.h index 7a8e6ecbf..3e0d9d5f1 100644 --- a/src/osal/osal.h +++ b/src/osal/osal.h @@ -81,11 +81,11 @@ typedef void (*osal_task_func_t)( void * ); #define STASK_INVOKE(_subtask, _status) (_status) = _subtask //------------- Sub Task Assert -------------// - #define STASK_ASSERT_ERR(_err) VERIFY_ERR(_err) - #define STASK_ASSERT_ERR_HDLR(_err, _func) VERIFY_ERR_HDLR(_err, _func) + #define STASK_ASSERT_ERR(_err) TU_VERIFY_ERR(_err) + #define STASK_ASSERT_ERR_HDLR(_err, _func) TU_VERIFY_ERR_HDLR(_err, _func) - #define STASK_ASSERT(_cond) VERIFY(_cond, TUSB_ERROR_OSAL_TASK_FAILED) - #define STASK_ASSERT_HDLR(_cond, _func) VERIFY_HDLR(_cond, _func) + #define STASK_ASSERT(_cond) TU_VERIFY(_cond, TUSB_ERROR_OSAL_TASK_FAILED) + #define STASK_ASSERT_HDLR(_cond, _func) TU_VERIFY_HDLR(_cond, _func) #endif #ifdef __cplusplus diff --git a/src/osal/osal_none.h b/src/osal/osal_none.h index b8cd2893c..3531686b4 100644 --- a/src/osal/osal_none.h +++ b/src/osal/osal_none.h @@ -121,11 +121,11 @@ static inline osal_task_t osal_task_create(osal_task_def_t* taskdef) //------------- Sub Task Assert -------------// #define STASK_RETURN(error) do { TASK_RESTART; return error; } while(0) -#define STASK_ASSERT_ERR(_err) VERIFY_ERR_HDLR(_err, verify_breakpoint(); TASK_RESTART, TUSB_ERROR_FAILED) -#define STASK_ASSERT_ERR_HDLR(_err, _func) VERIFY_ERR_HDLR(_err, verify_breakpoint(); _func; TASK_RESTART, TUSB_ERROR_FAILED ) +#define STASK_ASSERT_ERR(_err) TU_VERIFY_ERR_HDLR(_err, verify_breakpoint(); TASK_RESTART, TUSB_ERROR_FAILED) +#define STASK_ASSERT_ERR_HDLR(_err, _func) TU_VERIFY_ERR_HDLR(_err, verify_breakpoint(); _func; TASK_RESTART, TUSB_ERROR_FAILED ) -#define STASK_ASSERT(_cond) VERIFY_HDLR(_cond, verify_breakpoint(); TASK_RESTART, TUSB_ERROR_FAILED) -#define STASK_ASSERT_HDLR(_cond, _func) VERIFY_HDLR(_cond, verify_breakpoint(); _func; TASK_RESTART, TUSB_ERROR_FAILED) +#define STASK_ASSERT(_cond) TU_VERIFY_HDLR(_cond, verify_breakpoint(); TASK_RESTART, TUSB_ERROR_FAILED) +#define STASK_ASSERT_HDLR(_cond, _func) TU_VERIFY_HDLR(_cond, verify_breakpoint(); _func; TASK_RESTART, TUSB_ERROR_FAILED) //--------------------------------------------------------------------+ // QUEUE API diff --git a/src/portable/nxp/lpc11xx_lpc13xx/dcd_lpc_11uxx_13uxx.c b/src/portable/nxp/lpc11xx_lpc13xx/dcd_lpc_11uxx_13uxx.c index 68eef47e1..0eaecf1b8 100644 --- a/src/portable/nxp/lpc11xx_lpc13xx/dcd_lpc_11uxx_13uxx.c +++ b/src/portable/nxp/lpc11xx_lpc13xx/dcd_lpc_11uxx_13uxx.c @@ -104,7 +104,7 @@ typedef struct ATTR_PACKED volatile uint16_t active : 1 ; ///< The buffer is enabled. HW can use the buffer to store received OUT data or to transmit data on the IN endpoint. Software can only set this bit to ‘1’. As long as this bit is set to one, software is not allowed to update any of the values in this 32-bit word. In case software wants to deactivate the buffer, it must write a one to the corresponding “skip” bit in the USB Endpoint skip register. Hardware can only write this bit to zero. It will do this when it receives a short packet or when the NBytes field transitions to zero or when software has written a one to the “skip” bit. }dcd_11u_13u_qhd_t; -VERIFY_STATIC( sizeof(dcd_11u_13u_qhd_t) == 4, "size is not correct" ); +TU_VERIFY_STATIC( sizeof(dcd_11u_13u_qhd_t) == 4, "size is not correct" ); // NOTE data will be transferred as soon as dcd get request by dcd_pipe(_queue)_xfer using double buffering. // If there is another dcd_edpt_xfer request, the new request will be saved and executed when the first is done. diff --git a/src/portable/nxp/lpc17xx/dcd_lpc175x_6x.c b/src/portable/nxp/lpc17xx/dcd_lpc175x_6x.c index 948572129..a87e7d899 100644 --- a/src/portable/nxp/lpc17xx/dcd_lpc175x_6x.c +++ b/src/portable/nxp/lpc17xx/dcd_lpc175x_6x.c @@ -384,7 +384,7 @@ bool dcd_control_xfer(uint8_t rhport, tusb_dir_t dir, uint8_t * p_buffer, uint16 { (void) rhport; - VERIFY( !(length != 0 && p_buffer == NULL) ); + TU_VERIFY( !(length != 0 && p_buffer == NULL) ); // determine Endpoint where Data & Status phase occurred (IN or OUT) uint8_t const ep_data = (dir == TUSB_DIR_IN) ? 1 : 0; @@ -399,13 +399,13 @@ bool dcd_control_xfer(uint8_t rhport, tusb_dir_t dir, uint8_t * p_buffer, uint16 dcd_data.control_dma.remaining_bytes = length; // lpc17xx already received the first DATA OUT packet by now - VERIFY_ERR ( pipe_control_xfer(ep_data, p_buffer, length), false ); + TU_VERIFY_ERR ( pipe_control_xfer(ep_data, p_buffer, length), false ); } //------------- Status Phase (opposite direct to Data) -------------// if (dir == TUSB_DIR_OUT) { // only write for CONTROL OUT, CONTROL IN data will be retrieved in hal_dcd_isr // TODO ???? - VERIFY_ERR ( pipe_control_write(NULL, 0), false ); + TU_VERIFY_ERR ( pipe_control_write(NULL, 0), false ); } return true; diff --git a/src/portable/nxp/lpc17xx/dcd_lpc175x_6x.h b/src/portable/nxp/lpc17xx/dcd_lpc175x_6x.h index 1df1fcd30..4746b4acf 100644 --- a/src/portable/nxp/lpc17xx/dcd_lpc175x_6x.h +++ b/src/portable/nxp/lpc17xx/dcd_lpc175x_6x.h @@ -80,7 +80,7 @@ typedef struct ATTR_ALIGNED(4) // uint32_t iso_packet_size_addr; // iso only, can be omitted for non-iso }dcd_dma_descriptor_t; -VERIFY_STATIC( sizeof(dcd_dma_descriptor_t) == 16, "size is not correct"); // TODO not support ISO for now +TU_VERIFY_STATIC( sizeof(dcd_dma_descriptor_t) == 16, "size is not correct"); // TODO not support ISO for now //--------------------------------------------------------------------+ diff --git a/src/portable/nxp/lpc43xx_lpc18xx/dcd_lpc43xx.c b/src/portable/nxp/lpc43xx_lpc18xx/dcd_lpc43xx.c index 0b48ad1e6..61f829713 100644 --- a/src/portable/nxp/lpc43xx_lpc18xx/dcd_lpc43xx.c +++ b/src/portable/nxp/lpc43xx_lpc18xx/dcd_lpc43xx.c @@ -244,7 +244,7 @@ bool dcd_control_xfer(uint8_t rhport, tusb_dir_t dir, uint8_t * p_buffer, uint16 // wait until ENDPTSETUPSTAT before priming data/status in response TODO add time out while(lpc_usb->ENDPTSETUPSTAT & BIT_(0)) {} - VERIFY( !qhd->qtd_overlay.active ); + TU_VERIFY( !qhd->qtd_overlay.active ); dcd_qtd_t* qtd = &p_dcd->qtd[0]; qtd_init(qtd, p_buffer, length); @@ -295,7 +295,7 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc) { // TODO USB1 only has 4 non-control enpoint (USB0 has 5) // TODO not support ISO yet - VERIFY ( p_endpoint_desc->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS); + TU_VERIFY ( p_endpoint_desc->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS); tusb_dir_t dir = (p_endpoint_desc->bEndpointAddress & TUSB_DIR_IN_MASK) ? TUSB_DIR_IN : TUSB_DIR_OUT; @@ -313,7 +313,7 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc) volatile uint32_t * reg_control = get_reg_control_addr(rhport, ep_idx); // endpoint must not be already enabled - VERIFY( !( (*reg_control) & (ENDPTCTRL_MASK_ENABLE << (dir ? 16 : 0)) ) ); + TU_VERIFY( !( (*reg_control) & (ENDPTCTRL_MASK_ENABLE << (dir ? 16 : 0)) ) ); (*reg_control) |= ((p_endpoint_desc->bmAttributes.xfer << 2) | ENDPTCTRL_MASK_ENABLE | ENDPTCTRL_MASK_TOGGLE_RESET) << (dir ? 16 : 0); @@ -363,7 +363,7 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t { uint8_t ep_idx = edpt_addr2phy(ep_addr); - VERIFY ( pipe_add_xfer(rhport, ep_idx, buffer, total_bytes, true) ); + TU_VERIFY ( pipe_add_xfer(rhport, ep_idx, buffer, total_bytes, true) ); dcd_qhd_t* p_qhd = &dcd_data_ptr[rhport]->qhd[ ep_idx ]; dcd_qtd_t* p_qtd = &dcd_data_ptr[rhport]->qtd[ p_qhd->list_qtd_idx[0] ]; diff --git a/src/portable/nxp/lpc43xx_lpc18xx/dcd_lpc43xx.h b/src/portable/nxp/lpc43xx_lpc18xx/dcd_lpc43xx.h index 92e24c1fb..1476c0d30 100644 --- a/src/portable/nxp/lpc43xx_lpc18xx/dcd_lpc43xx.h +++ b/src/portable/nxp/lpc43xx_lpc18xx/dcd_lpc43xx.h @@ -122,7 +122,7 @@ typedef struct uint8_t reserved; } dcd_qtd_t; -VERIFY_STATIC( sizeof(dcd_qtd_t) == 32, "size is not correct"); +TU_VERIFY_STATIC( sizeof(dcd_qtd_t) == 32, "size is not correct"); typedef struct { @@ -153,7 +153,7 @@ typedef struct uint8_t reserved[16-DCD_QTD_PER_QHD_MAX]; } dcd_qhd_t; -VERIFY_STATIC( sizeof(dcd_qhd_t) == 64, "size is not correct"); +TU_VERIFY_STATIC( sizeof(dcd_qhd_t) == 64, "size is not correct"); #ifdef __cplusplus diff --git a/src/portable/nxp/lpc43xx_lpc18xx/hal_lpc43xx.c b/src/portable/nxp/lpc43xx_lpc18xx/hal_lpc43xx.c index 18745d03e..213b8dd99 100644 --- a/src/portable/nxp/lpc43xx_lpc18xx/hal_lpc43xx.c +++ b/src/portable/nxp/lpc43xx_lpc18xx/hal_lpc43xx.c @@ -86,7 +86,7 @@ bool tusb_hal_init(void) //------------- USB0 -------------// #if CFG_TUSB_RHPORT0_MODE CGU_EnableEntity(CGU_CLKSRC_PLL0, DISABLE); /* Disable PLL first */ - VERIFY( CGU_ERROR_SUCCESS == CGU_SetPLL0()); /* the usb core require output clock = 480MHz */ + TU_VERIFY( CGU_ERROR_SUCCESS == CGU_SetPLL0()); /* the usb core require output clock = 480MHz */ CGU_EntityConnect(CGU_CLKSRC_XTAL_OSC, CGU_CLKSRC_PLL0); CGU_EnableEntity(CGU_CLKSRC_PLL0, ENABLE); /* Enable PLL after all setting is done */ diff --git a/src/tusb.c b/src/tusb.c index 0ef1301a4..b064d03f9 100644 --- a/src/tusb.c +++ b/src/tusb.c @@ -49,7 +49,7 @@ tusb_error_t tusb_init(void) // skip if already initialized if (_initialized) return TUSB_ERROR_NONE; - VERIFY( tusb_hal_init(), TUSB_ERROR_FAILED ) ; // hardware init + TU_VERIFY( tusb_hal_init(), TUSB_ERROR_FAILED ) ; // hardware init #if MODE_HOST_SUPPORTED TU_ASSERT_ERR( usbh_init() ); // host stack init -- cgit v1.3.1 From 7b35cd0203bc409d7c1aefc075672103cb4a913e Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 21 Aug 2018 14:51:59 +0700 Subject: add string desc helper --- src/common/tusb_types.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'src/common') diff --git a/src/common/tusb_types.h b/src/common/tusb_types.h index c3ed4f2bd..ee9e849bf 100644 --- a/src/common/tusb_types.h +++ b/src/common/tusb_types.h @@ -416,9 +416,14 @@ static inline uint8_t descriptor_len(uint8_t const p_desc[]) return p_desc[DESC_OFFSET_LEN]; } +// Length of the string descriptors in bytes with slen characters +#define TUD_DESC_STRLEN(_slen) (2*(_slen) + 2) + +// Header of string descriptors with len + string type +#define TUD_DESC_STR_HEADER(_slen) ( (uint16_t) ( (TUSB_DESC_STRING << 8 ) | TUD_DESC_STRLEN(_slen)) ) // Convert comma-separated string to descriptor unicode format -#define TUD_DESC_STRCONV( ... ) (const uint16_t[]) { (TUSB_DESC_STRING << 8 ) | (2*VA_ARGS_NUM_(__VA_ARGS__) + 2), __VA_ARGS__ } +#define TUD_DESC_STRCONV( ... ) (const uint16_t[]) { TUD_DESC_STR_HEADER(VA_ARGS_NUM_(__VA_ARGS__)), __VA_ARGS__ } #ifdef __cplusplus } -- cgit v1.3.1 From c5d2f661e76adbe2f047c2f3a405ed60262ecb9b Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 23 Aug 2018 20:09:28 +0700 Subject: rename common func to avoid conflict --- src/class/cdc/cdc_device.c | 4 +- src/class/cdc/cdc_host.c | 2 +- src/class/hid/hid_device.c | 14 ++--- src/class/msc/msc_device.c | 4 +- src/common/tusb_common.h | 64 +++++++--------------- src/common/tusb_fifo.c | 6 +- src/device/usbd.c | 16 +++--- src/host/ehci/ehci.c | 28 +++++----- src/host/ohci/ohci.c | 24 ++++---- src/host/usbh.c | 2 +- src/portable/nordic/nrf5x/dcd_nrf5x.c | 4 +- .../nxp/lpc11xx_lpc13xx/dcd_lpc_11uxx_13uxx.c | 2 +- src/portable/nxp/lpc17xx/dcd_lpc175x_6x.c | 4 +- src/portable/nxp/lpc43xx_lpc18xx/dcd_lpc43xx.c | 2 +- tests/lpc18xx_43xx/test/host/ehci/test_ehci_init.c | 4 +- .../test/host/ehci/test_pipe_bulk_open.c | 8 +-- .../test/host/ehci/test_pipe_bulk_xfer.c | 4 +- .../test/host/ehci/test_pipe_control_open.c | 6 +- .../test/host/ehci/test_pipe_interrupt_open.c | 24 ++++---- .../test/host/ehci/test_pipe_interrupt_xfer.c | 4 +- tests/support/ehci_controller_fake.c | 12 ++-- tests/support/type_helper.h | 6 +- 22 files changed, 109 insertions(+), 135 deletions(-) (limited to 'src/common') diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index 075a7f8db..2a598f051 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -208,7 +208,7 @@ tusb_error_t cdcd_open(uint8_t rhport, tusb_desc_interface_t const * p_interface { if ( CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL != p_interface_desc->bInterfaceSubClass) return TUSB_ERROR_CDC_UNSUPPORTED_SUBCLASS; - if ( !(is_in_range(CDC_COMM_PROTOCOL_ATCOMMAND, p_interface_desc->bInterfaceProtocol, CDC_COMM_PROTOCOL_ATCOMMAND_CDMA) || + if ( !(tu_within(CDC_COMM_PROTOCOL_ATCOMMAND, p_interface_desc->bInterfaceProtocol, CDC_COMM_PROTOCOL_ATCOMMAND_CDMA) || 0xff == p_interface_desc->bInterfaceProtocol) ) { return TUSB_ERROR_CDC_UNSUPPORTED_PROTOCOL; @@ -282,7 +282,7 @@ tusb_error_t cdcd_control_request_st(uint8_t rhport, tusb_control_request_t cons if ( (CDC_REQUEST_GET_LINE_CODING == p_request->bRequest) || (CDC_REQUEST_SET_LINE_CODING == p_request->bRequest) ) { - uint16_t len = min16_of(sizeof(cdc_line_coding_t), p_request->wLength); + uint16_t len = tu_min16(sizeof(cdc_line_coding_t), p_request->wLength); usbd_control_xfer_st(rhport, p_request->bmRequestType_bit.direction, &p_cdc->line_coding, len); // Invoke callback diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index 6950759d1..ca448ba5e 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -149,7 +149,7 @@ tusb_error_t cdch_open_subtask(uint8_t dev_addr, tusb_desc_interface_t const *p_ if ( CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL != p_interface_desc->bInterfaceSubClass) return TUSB_ERROR_CDC_UNSUPPORTED_SUBCLASS; - if ( !(is_in_range(CDC_COMM_PROTOCOL_ATCOMMAND, p_interface_desc->bInterfaceProtocol, CDC_COMM_PROTOCOL_ATCOMMAND_CDMA) || + if ( !(tu_within(CDC_COMM_PROTOCOL_ATCOMMAND, p_interface_desc->bInterfaceProtocol, CDC_COMM_PROTOCOL_ATCOMMAND_CDMA) || 0xff == p_interface_desc->bInterfaceProtocol) ) { return TUSB_ERROR_CDC_UNSUPPORTED_PROTOCOL; diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index 410359e6d..b1cd1d1bd 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -412,8 +412,8 @@ tusb_error_t hidd_control_request_st(uint8_t rhport, tusb_control_request_t cons //------------- STD Request -------------// if (p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD) { - uint8_t const desc_type = u16_high_u8(p_request->wValue); - uint8_t const desc_index = u16_low_u8 (p_request->wValue); + uint8_t const desc_type = tu_u16_high(p_request->wValue); + uint8_t const desc_index = tu_u16_low (p_request->wValue); (void) desc_index; if (p_request->bRequest == TUSB_REQ_GET_DESCRIPTOR && desc_type == HID_DESC_TYPE_REPORT) @@ -434,8 +434,8 @@ tusb_error_t hidd_control_request_st(uint8_t rhport, tusb_control_request_t cons if( HID_REQ_CONTROL_GET_REPORT == p_request->bRequest ) { // wValue = Report Type | Report ID - uint8_t const report_type = u16_high_u8(p_request->wValue); - uint8_t const report_id = u16_low_u8(p_request->wValue); + uint8_t const report_type = tu_u16_high(p_request->wValue); + uint8_t const report_id = tu_u16_low(p_request->wValue); uint16_t xferlen; if ( p_hid->get_report_cb ) @@ -455,8 +455,8 @@ tusb_error_t hidd_control_request_st(uint8_t rhport, tusb_control_request_t cons usbd_control_xfer_st(rhport, p_request->bmRequestType_bit.direction, _usbd_ctrl_buf, p_request->wLength); // wValue = Report Type | Report ID - uint8_t const report_type = u16_high_u8(p_request->wValue); - uint8_t const report_id = u16_low_u8(p_request->wValue); + uint8_t const report_type = tu_u16_high(p_request->wValue); + uint8_t const report_id = tu_u16_low(p_request->wValue); if ( p_hid->set_report_cb ) { @@ -466,7 +466,7 @@ tusb_error_t hidd_control_request_st(uint8_t rhport, tusb_control_request_t cons else if (HID_REQ_CONTROL_SET_IDLE == p_request->bRequest) { // TODO idle rate of report - p_hid->idle_rate = u16_high_u8(p_request->wValue); + p_hid->idle_rate = tu_u16_high(p_request->wValue); dcd_control_status(rhport, p_request->bmRequestType_bit.direction); } else if (HID_REQ_CONTROL_GET_IDLE == p_request->bRequest) diff --git a/src/class/msc/msc_device.c b/src/class/msc/msc_device.c index a11212c4b..3335ad9b3 100644 --- a/src/class/msc/msc_device.c +++ b/src/class/msc/msc_device.c @@ -531,7 +531,7 @@ static void proc_read10_cmd(uint8_t rhport, mscd_interface_t* p_msc) uint32_t const lba = rdwr10_get_lba(p_cbw->command) + (p_msc->xferred_len / block_sz); // remaining bytes capped at class buffer - int32_t nbytes = (int32_t) min32_of(sizeof(_mscd_buf), p_cbw->xfer_bytes-p_msc->xferred_len); + int32_t nbytes = (int32_t) tu_min32(sizeof(_mscd_buf), p_cbw->xfer_bytes-p_msc->xferred_len); // Application can consume smaller bytes nbytes = tud_msc_read10_cb(p_cbw->lun, lba, p_msc->xferred_len % block_sz, _mscd_buf, (uint32_t) nbytes); @@ -561,7 +561,7 @@ static void proc_write10_cmd(uint8_t rhport, mscd_interface_t* p_msc) msc_cbw_t const * p_cbw = &p_msc->cbw; // remaining bytes capped at class buffer - int32_t nbytes = (int32_t) min32_of(sizeof(_mscd_buf), p_cbw->xfer_bytes-p_msc->xferred_len); + int32_t nbytes = (int32_t) tu_min32(sizeof(_mscd_buf), p_cbw->xfer_bytes-p_msc->xferred_len); // Write10 callback will be called later when usb transfer complete TU_ASSERT( dcd_edpt_xfer(rhport, p_msc->ep_out, _mscd_buf, nbytes), ); diff --git a/src/common/tusb_common.h b/src/common/tusb_common.h index e8baa9de4..778e70676 100644 --- a/src/common/tusb_common.h +++ b/src/common/tusb_common.h @@ -151,119 +151,94 @@ static inline bool mem_all_zero(void const* buffer, uint32_t size) //------------- Conversion -------------// -/// form an uint32_t from 4 x uint8_t -static inline uint32_t u32_from_u8(uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4) ATTR_ALWAYS_INLINE ATTR_CONST; -static inline uint32_t u32_from_u8(uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4) +static inline uint32_t tu_u32_from_u8(uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4) { return ( ((uint32_t) b1) << 24) + ( ((uint32_t) b2) << 16) + ( ((uint32_t) b3) << 8) + b4; } -static inline uint8_t u16_high_u8(uint16_t u16) ATTR_CONST ATTR_ALWAYS_INLINE; -static inline uint8_t u16_high_u8(uint16_t u16) +static inline uint8_t tu_u16_high(uint16_t u16) { return (uint8_t) ( ((uint16_t) (u16 >> 8)) & 0x00ff); } -static inline uint8_t u16_low_u8(uint16_t u16) ATTR_CONST ATTR_ALWAYS_INLINE; -static inline uint8_t u16_low_u8(uint16_t u16) +static inline uint8_t tu_u16_low(uint16_t u16) { return (uint8_t) (u16 & 0x00ff); } -static inline uint16_t u16_le2be(uint16_t u16) ATTR_CONST ATTR_ALWAYS_INLINE; -static inline uint16_t u16_le2be(uint16_t u16) +static inline uint16_t tu_u16_le2be(uint16_t u16) { - return ((uint16_t)(u16_low_u8(u16) << 8)) | u16_high_u8(u16); + return ((uint16_t)(tu_u16_low(u16) << 8)) | tu_u16_high(u16); } //------------- Min -------------// -static inline uint8_t min8_of(uint8_t x, uint8_t y) ATTR_ALWAYS_INLINE ATTR_CONST; -static inline uint8_t min8_of(uint8_t x, uint8_t y) +static inline uint8_t tu_min8(uint8_t x, uint8_t y) { return (x < y) ? x : y; } -static inline uint16_t min16_of(uint16_t x, uint16_t y) ATTR_ALWAYS_INLINE ATTR_CONST; -static inline uint16_t min16_of(uint16_t x, uint16_t y) +static inline uint16_t tu_min16(uint16_t x, uint16_t y) { return (x < y) ? x : y; } -static inline uint32_t min32_of(uint32_t x, uint32_t y) ATTR_ALWAYS_INLINE ATTR_CONST; -static inline uint32_t min32_of(uint32_t x, uint32_t y) +static inline uint32_t tu_min32(uint32_t x, uint32_t y) { return (x < y) ? x : y; } //------------- Max -------------// -static inline uint32_t max32_of(uint32_t x, uint32_t y) ATTR_ALWAYS_INLINE ATTR_CONST; -static inline uint32_t max32_of(uint32_t x, uint32_t y) +static inline uint32_t tu_max32(uint32_t x, uint32_t y) { return (x > y) ? x : y; } -static inline uint16_t max16_of(uint16_t x, uint16_t y) ATTR_ALWAYS_INLINE ATTR_CONST; -static inline uint16_t max16_of(uint16_t x, uint16_t y) +static inline uint16_t tu_max16(uint16_t x, uint16_t y) { return (x > y) ? x : y; } //------------- Align -------------// -static inline uint32_t align32 (uint32_t value) ATTR_ALWAYS_INLINE ATTR_CONST; -static inline uint32_t align32 (uint32_t value) +static inline uint32_t tu_align32 (uint32_t value) { return (value & 0xFFFFFFE0UL); } -static inline uint32_t align16 (uint32_t value) ATTR_ALWAYS_INLINE ATTR_CONST; -static inline uint32_t align16 (uint32_t value) +static inline uint32_t tu_align16 (uint32_t value) { return (value & 0xFFFFFFF0UL); } -static inline uint32_t align_n (uint32_t alignment, uint32_t value) ATTR_ALWAYS_INLINE ATTR_CONST; -static inline uint32_t align_n (uint32_t alignment, uint32_t value) +static inline uint32_t tu_align_n (uint32_t alignment, uint32_t value) { return value & ((uint32_t) ~(alignment-1)); } -static inline uint32_t align4k (uint32_t value) ATTR_ALWAYS_INLINE ATTR_CONST; -static inline uint32_t align4k (uint32_t value) +static inline uint32_t tu_align4k (uint32_t value) { return (value & 0xFFFFF000UL); } -static inline uint32_t offset4k(uint32_t value) ATTR_ALWAYS_INLINE ATTR_CONST; -static inline uint32_t offset4k(uint32_t value) +static inline uint32_t tu_offset4k(uint32_t value) { return (value & 0xFFFUL); } //------------- Mathematics -------------// -static inline uint32_t abs_of(int32_t value) ATTR_ALWAYS_INLINE ATTR_CONST; -static inline uint32_t abs_of(int32_t value) +static inline uint32_t tu_abs(int32_t value) { return (value < 0) ? (-value) : value; } /// inclusive range checking -static inline bool is_in_range(uint32_t lower, uint32_t value, uint32_t upper) ATTR_ALWAYS_INLINE ATTR_CONST; -static inline bool is_in_range(uint32_t lower, uint32_t value, uint32_t upper) +static inline bool tu_within(uint32_t lower, uint32_t value, uint32_t upper) { return (lower <= value) && (value <= upper); } -/// exclusive range checking -static inline bool is_in_range_exclusive(uint32_t lower, uint32_t value, uint32_t upper) ATTR_ALWAYS_INLINE ATTR_CONST; -static inline bool is_in_range_exclusive(uint32_t lower, uint32_t value, uint32_t upper) -{ - return (lower < value) && (value < upper); -} - // TODO use clz -static inline uint8_t log2_of(uint32_t value) ATTR_ALWAYS_INLINE ATTR_CONST; -static inline uint8_t log2_of(uint32_t value) +static inline uint8_t tu_log2(uint32_t value) { uint8_t result = 0; // log2 of a value is its MSB's position @@ -275,8 +250,7 @@ static inline uint8_t log2_of(uint32_t value) } // return the number of set bits in value -static inline uint8_t cardinality_of(uint32_t value) ATTR_ALWAYS_INLINE ATTR_CONST; -static inline uint8_t cardinality_of(uint32_t value) +static inline uint8_t tu_cardof(uint32_t value) { // Brian Kernighan's method goes through as many iterations as there are set bits. So if we have a 32-bit word with only // the high bit set, then it will only go once through the loop diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index 09763bee0..e90264f8b 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -54,7 +54,7 @@ #endif -static inline uint16_t min16_of(uint16_t x, uint16_t y) +static inline uint16_t tu_min16(uint16_t x, uint16_t y) { return (x < y) ? x : y; } @@ -136,7 +136,7 @@ uint16_t tu_fifo_read_n (tu_fifo_t* f, void * p_buffer, uint16_t count) if( tu_fifo_empty(f) ) return 0; /* Limit up to fifo's count */ - count = min16_of(count, f->count); + count = tu_min16(count, f->count); if( count == 0 ) return 0; mutex_lock_if_needed(f); @@ -145,7 +145,7 @@ uint16_t tu_fifo_read_n (tu_fifo_t* f, void * p_buffer, uint16_t count) * case 1: ....RxxxxW....... * case 2: xxxxxW....Rxxxxxx */ -// uint16_t index2upper = min16_of(count, f->count-f->rd_idx); +// uint16_t index2upper = tu_min16(count, f->count-f->rd_idx); uint8_t* p_buf = (uint8_t*) p_buffer; uint16_t len = 0; diff --git a/src/device/usbd.c b/src/device/usbd.c index 79ad8ffa2..ea5e24884 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -377,9 +377,9 @@ static tusb_error_t proc_control_request_st(uint8_t rhport, tusb_control_request //------------- Class/Interface Specific Request -------------// else if ( TUSB_REQ_RCPT_INTERFACE == p_request->bmRequestType_bit.recipient ) { - if (_usbd_dev.itf2drv[ u16_low_u8(p_request->wIndex) ] < USBD_CLASS_DRIVER_COUNT) + if (_usbd_dev.itf2drv[ tu_u16_low(p_request->wIndex) ] < USBD_CLASS_DRIVER_COUNT) { - STASK_INVOKE( usbd_class_drivers[ _usbd_dev.itf2drv[ u16_low_u8(p_request->wIndex) ] ].control_req_st(rhport, p_request), error ); + STASK_INVOKE( usbd_class_drivers[ _usbd_dev.itf2drv[ tu_u16_low(p_request->wIndex) ] ].control_req_st(rhport, p_request), error ); }else { dcd_control_stall(rhport); // Stall unsupported request @@ -392,7 +392,7 @@ static tusb_error_t proc_control_request_st(uint8_t rhport, tusb_control_request { if (TUSB_REQ_GET_STATUS == p_request->bRequest ) { - uint16_t status = dcd_edpt_stalled(rhport, u16_low_u8(p_request->wIndex)) ? 0x0001 : 0x0000; + uint16_t status = dcd_edpt_stalled(rhport, tu_u16_low(p_request->wIndex)) ? 0x0001 : 0x0000; memcpy(_usbd_ctrl_buf, &status, 2); usbd_control_xfer_st(rhport, p_request->bmRequestType_bit.direction, _usbd_ctrl_buf, 2); @@ -400,13 +400,13 @@ static tusb_error_t proc_control_request_st(uint8_t rhport, tusb_control_request else if (TUSB_REQ_CLEAR_FEATURE == p_request->bRequest ) { // only endpoint feature is halted/stalled - dcd_edpt_clear_stall(rhport, u16_low_u8(p_request->wIndex)); + dcd_edpt_clear_stall(rhport, tu_u16_low(p_request->wIndex)); dcd_control_status(rhport, p_request->bmRequestType_bit.direction); } else if (TUSB_REQ_SET_FEATURE == p_request->bRequest ) { // only endpoint feature is halted/stalled - dcd_edpt_stall(rhport, u16_low_u8(p_request->wIndex)); + dcd_edpt_stall(rhport, tu_u16_low(p_request->wIndex)); dcd_control_status(rhport, p_request->bmRequestType_bit.direction); } else @@ -484,8 +484,8 @@ static uint16_t get_descriptor(uint8_t rhport, tusb_control_request_t const * co { (void) rhport; - tusb_desc_type_t const desc_type = (tusb_desc_type_t) u16_high_u8(p_request->wValue); - uint8_t const desc_index = u16_low_u8( p_request->wValue ); + tusb_desc_type_t const desc_type = (tusb_desc_type_t) tu_u16_high(p_request->wValue); + uint8_t const desc_index = tu_u16_low( p_request->wValue ); uint8_t const * desc_data = NULL ; uint16_t len = 0; @@ -532,7 +532,7 @@ static uint16_t get_descriptor(uint8_t rhport, tusb_control_request_t const * co TU_ASSERT( desc_data != NULL, 0); // up to Host's length - len = min16_of(p_request->wLength, len ); + len = tu_min16(p_request->wLength, len ); (*pp_buffer) = desc_data; return len; diff --git a/src/host/ehci/ehci.c b/src/host/ehci/ehci.c index 32fcc8140..84821e3f5 100644 --- a/src/host/ehci/ehci.c +++ b/src/host/ehci/ehci.c @@ -604,14 +604,14 @@ static void period_list_xfer_complete_isr(uint8_t hostid, uint8_t interval_ms) // TODO abstract max loop guard for period while( !next_item.terminate && - !(interval_ms > 1 && period_1ms_addr == align32(next_item.address)) && + !(interval_ms > 1 && period_1ms_addr == tu_align32(next_item.address)) && max_loop < (HCD_MAX_ENDPOINT + EHCI_MAX_ITD + EHCI_MAX_SITD)*CFG_TUSB_HOST_DEVICE_MAX) { switch ( next_item.type ) { case EHCI_QUEUE_ELEMENT_QHD: { - ehci_qhd_t *p_qhd_int = (ehci_qhd_t *) align32(next_item.address); + ehci_qhd_t *p_qhd_int = (ehci_qhd_t *) tu_align32(next_item.address); if ( !p_qhd_int->qtd_overlay.halted ) { qhd_xfer_complete_isr(p_qhd_int); @@ -653,7 +653,7 @@ static void qhd_xfer_error_isr(ehci_qhd_t * p_qhd) if ( TUSB_XFER_CONTROL == xfer_type ) { - p_qhd->total_xferred_bytes -= min8_of(8, p_qhd->total_xferred_bytes); // subtract setup size + p_qhd->total_xferred_bytes -= tu_min8(8, p_qhd->total_xferred_bytes); // subtract setup size // control cannot be halted --> clear all qtd list p_qhd->p_qtd_list_head = NULL; @@ -702,14 +702,14 @@ static void xfer_error_isr(uint8_t hostid) // TODO abstract max loop guard for period while( !next_item.terminate && - !(interval_ms > 1 && period_1ms_addr == align32(next_item.address)) && + !(interval_ms > 1 && period_1ms_addr == tu_align32(next_item.address)) && period_max_loop < (HCD_MAX_ENDPOINT + EHCI_MAX_ITD + EHCI_MAX_SITD)*CFG_TUSB_HOST_DEVICE_MAX) { switch ( next_item.type ) { case EHCI_QUEUE_ELEMENT_QHD: { - ehci_qhd_t *p_qhd_int = (ehci_qhd_t *) align32(next_item.address); + ehci_qhd_t *p_qhd_int = (ehci_qhd_t *) tu_align32(next_item.address); qhd_xfer_error_isr(p_qhd_int); } break; @@ -828,7 +828,7 @@ static inline ehci_qhd_t* get_async_head(uint8_t hostid) static inline ehci_link_t* get_period_head(uint8_t hostid, uint8_t interval_ms) { return (ehci_link_t*) (&ehci_data.period_head_arr[ hostid_to_data_idx(hostid) ] - [ log2_of( min8_of(EHCI_FRAMELIST_SIZE, interval_ms) ) ] ); + [ tu_log2( tu_min8(EHCI_FRAMELIST_SIZE, interval_ms) ) ] ); } #endif @@ -869,7 +869,7 @@ static inline tusb_xfer_type_t qhd_get_xfer_type(ehci_qhd_t const * p_qhd) static inline ehci_qhd_t* qhd_next(ehci_qhd_t const * p_qhd) { - return (ehci_qhd_t*) align32(p_qhd->next.address); + return (ehci_qhd_t*) tu_align32(p_qhd->next.address); } static inline ehci_qhd_t* qhd_get_from_pipe_handle(pipe_handle_t pipe_hdl) @@ -907,7 +907,7 @@ static inline ehci_qtd_t* qtd_find_free(uint8_t dev_addr) static inline ehci_qtd_t* qtd_next(ehci_qtd_t const * p_qtd ) { - return (ehci_qtd_t*) align32(p_qtd->next.address); + return (ehci_qtd_t*) tu_align32(p_qtd->next.address); } static inline void qtd_remove_1st_from_qhd(ehci_qhd_t *p_qhd) @@ -965,7 +965,7 @@ static void qhd_init(ehci_qhd_t *p_qhd, uint8_t dev_addr, uint16_t max_packet_si (interval == 2) ? BIN8(10101010) : BIN8(01000100); }else { - p_qhd->interval_ms = (uint8_t) min16_of( 1 << (interval-4), 255 ); + p_qhd->interval_ms = (uint8_t) tu_min16( 1 << (interval-4), 255 ); p_qhd->interrupt_smask = BIT_(interval % 8); } }else @@ -1019,7 +1019,7 @@ static void qtd_init(ehci_qtd_t* p_qtd, uint32_t data_ptr, uint16_t total_bytes) p_qtd->buffer[0] = data_ptr; for(uint8_t i=1; i<5; i++) { - p_qtd->buffer[i] |= align4k( p_qtd->buffer[i-1] ) + 4096; + p_qtd->buffer[i] |= tu_align4k( p_qtd->buffer[i-1] ) + 4096; } } @@ -1032,15 +1032,15 @@ static inline void list_insert(ehci_link_t *current, ehci_link_t *new, uint8_t n static inline ehci_link_t* list_next(ehci_link_t *p_link_pointer) { - return (ehci_link_t*) align32(p_link_pointer->address); + return (ehci_link_t*) tu_align32(p_link_pointer->address); } static ehci_link_t* list_find_previous_item(ehci_link_t* p_head, ehci_link_t* p_current) { ehci_link_t *p_prev = p_head; uint32_t max_loop = 0; - while( (align32(p_prev->address) != (uint32_t) p_head) && // not loop around - (align32(p_prev->address) != (uint32_t) p_current) && // not found yet + while( (tu_align32(p_prev->address) != (uint32_t) p_head) && // not loop around + (tu_align32(p_prev->address) != (uint32_t) p_current) && // not found yet !p_prev->terminate && // not advanceable max_loop < HCD_MAX_ENDPOINT) { @@ -1048,7 +1048,7 @@ static ehci_link_t* list_find_previous_item(ehci_link_t* p_head, ehci_link_t* p_ max_loop++; } - return (align32(p_prev->address) != (uint32_t) p_head) ? p_prev : NULL; + return (tu_align32(p_prev->address) != (uint32_t) p_head) ? p_prev : NULL; } static tusb_error_t list_remove_qhd(ehci_link_t* p_head, ehci_link_t* p_remove) diff --git a/src/host/ohci/ohci.c b/src/host/ohci/ohci.c index 644dbfa0f..1c9f3f293 100644 --- a/src/host/ohci/ohci.c +++ b/src/host/ohci/ohci.c @@ -389,15 +389,15 @@ static ohci_ed_t * ed_list_find_previous(ohci_ed_t const * p_head, ohci_ed_t con TU_ASSERT(p_prev, NULL); - while ( align16(p_prev->next_ed) != 0 && /* not reach null */ - align16(p_prev->next_ed) != (uint32_t) p_ed && /* not found yet */ + while ( tu_align16(p_prev->next_ed) != 0 && /* not reach null */ + tu_align16(p_prev->next_ed) != (uint32_t) p_ed && /* not found yet */ max_loop > 0) { - p_prev = (ohci_ed_t const *) align16(p_prev->next_ed); + p_prev = (ohci_ed_t const *) tu_align16(p_prev->next_ed); max_loop--; } - return ( align16(p_prev->next_ed) == (uint32_t) p_ed ) ? (ohci_ed_t*) p_prev : NULL; + return ( tu_align16(p_prev->next_ed) == (uint32_t) p_ed ) ? (ohci_ed_t*) p_prev : NULL; } static void ed_list_insert(ohci_ed_t * p_pre, ohci_ed_t * p_ed) @@ -410,7 +410,7 @@ static void ed_list_remove(ohci_ed_t * p_head, ohci_ed_t * p_ed) { ohci_ed_t * const p_prev = ed_list_find_previous(p_head, p_ed); - p_prev->next_ed = (p_prev->next_ed & 0x0fUL) | align16(p_ed->next_ed); + p_prev->next_ed = (p_prev->next_ed & 0x0fUL) | tu_align16(p_ed->next_ed); // point the removed ED's next pointer to list head to make sure HC can always safely move away from this ED p_ed->next_ed = (uint32_t) p_head; p_ed->used = 0; // free ED @@ -457,13 +457,13 @@ static ohci_gtd_t * gtd_find_free(uint8_t dev_addr) static void td_insert_to_ed(ohci_ed_t* p_ed, ohci_gtd_t * p_gtd) { // tail is always NULL - if ( align16(p_ed->td_head.address) == 0 ) + if ( tu_align16(p_ed->td_head.address) == 0 ) { // TD queue is empty --> head = TD p_ed->td_head.address |= (uint32_t) p_gtd; } else { // TODO currently only support queue up to 2 TD each endpoint at a time - ((ohci_gtd_t*) align16(p_ed->td_head.address))->next_td = (uint32_t) p_gtd; + ((ohci_gtd_t*) tu_align16(p_ed->td_head.address))->next_td = (uint32_t) p_gtd; } } @@ -520,7 +520,7 @@ tusb_error_t hcd_pipe_close(pipe_handle_t pipe_hdl) bool hcd_pipe_is_busy(pipe_handle_t pipe_hdl) { ohci_ed_t const * const p_ed = ed_from_pipe_handle(pipe_hdl); - return align16(p_ed->td_head.address) != align16(p_ed->td_tail.address); + return tu_align16(p_ed->td_head.address) != tu_align16(p_ed->td_tail.address); } bool hcd_pipe_is_error(pipe_handle_t pipe_hdl) @@ -601,8 +601,8 @@ static inline ohci_ed_t* gtd_get_ed(ohci_gtd_t const * const p_qtd) static inline uint32_t gtd_xfer_byte_left(uint32_t buffer_end, uint32_t current_buffer) ATTR_CONST ATTR_ALWAYS_INLINE; static inline uint32_t gtd_xfer_byte_left(uint32_t buffer_end, uint32_t current_buffer) { // 5.2.9 OHCI sample code - return (align4k(buffer_end ^ current_buffer) ? 0x1000 : 0) + - offset4k(buffer_end) - offset4k(current_buffer) + 1; + return (tu_align4k(buffer_end ^ current_buffer) ? 0x1000 : 0) + + tu_offset4k(buffer_end) - tu_offset4k(current_buffer) + 1; } static void done_queue_isr(uint8_t hostid) @@ -610,7 +610,7 @@ static void done_queue_isr(uint8_t hostid) uint8_t max_loop = (CFG_TUSB_HOST_DEVICE_MAX+1)*(HCD_MAX_XFER+OHCI_MAX_ITD); // done head is written in reversed order of completion --> need to reverse the done queue first - ohci_td_item_t* td_head = list_reverse ( (ohci_td_item_t*) align16(ohci_data.hcca.done_head) ); + ohci_td_item_t* td_head = list_reverse ( (ohci_td_item_t*) tu_align16(ohci_data.hcca.done_head) ); while( td_head != NULL && max_loop > 0) { @@ -637,7 +637,7 @@ static void done_queue_isr(uint8_t hostid) if ((event != TUSB_EVENT_XFER_COMPLETE)) { p_ed->td_tail.address &= 0x0Ful; - p_ed->td_tail.address |= align16(p_ed->td_head.address); // mark halted EP as empty queue + p_ed->td_tail.address |= tu_align16(p_ed->td_head.address); // mark halted EP as empty queue if ( event == TUSB_EVENT_XFER_STALLED ) p_ed->is_stalled = 1; } diff --git a/src/host/usbh.c b/src/host/usbh.c index 6d1cd37ad..8b858b2de 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -643,7 +643,7 @@ static inline uint8_t get_configure_number_for_device(tusb_desc_device_t* dev_de // invoke callback to ask user which configuration to select if (tuh_device_attached_cb) { - config_num = min8_of(1, tuh_device_attached_cb(dev_desc) ); + config_num = tu_min8(1, tuh_device_attached_cb(dev_desc) ); } return config_num; diff --git a/src/portable/nordic/nrf5x/dcd_nrf5x.c b/src/portable/nordic/nrf5x/dcd_nrf5x.c index 72cd8d0b1..1c91779a7 100644 --- a/src/portable/nordic/nrf5x/dcd_nrf5x.c +++ b/src/portable/nordic/nrf5x/dcd_nrf5x.c @@ -178,7 +178,7 @@ static void edpt_dma_end(void) static void xact_control_start(void) { // Each transaction is up to 64 bytes - uint8_t const xact_len = min16_of(_dcd.control.total_len-_dcd.control.actual_len, MAX_PACKET_SIZE); + uint8_t const xact_len = tu_min16(_dcd.control.total_len-_dcd.control.actual_len, MAX_PACKET_SIZE); if ( _dcd.control.dir == TUSB_DIR_OUT ) { @@ -274,7 +274,7 @@ static void xact_in_prepare(uint8_t epnum) nom_xfer_t* xfer = get_td(epnum, TUSB_DIR_IN); // Each transaction is up to Max Packet Size - uint8_t const xact_len = min16_of(xfer->total_len - xfer->actual_len, xfer->mps); + uint8_t const xact_len = tu_min16(xfer->total_len - xfer->actual_len, xfer->mps); NRF_USBD->EPIN[epnum].PTR = (uint32_t) xfer->buffer; NRF_USBD->EPIN[epnum].MAXCNT = xact_len; diff --git a/src/portable/nxp/lpc11xx_lpc13xx/dcd_lpc_11uxx_13uxx.c b/src/portable/nxp/lpc11xx_lpc13xx/dcd_lpc_11uxx_13uxx.c index 0eaecf1b8..3e536312a 100644 --- a/src/portable/nxp/lpc11xx_lpc13xx/dcd_lpc_11uxx_13uxx.c +++ b/src/portable/nxp/lpc11xx_lpc13xx/dcd_lpc_11uxx_13uxx.c @@ -497,7 +497,7 @@ bool dcd_edpt_busy(edpt_hdl_t edpt_hdl) static void queue_xfer_to_buffer(uint8_t ep_id, uint8_t buff_idx, uint16_t buff_addr_offset, uint16_t total_bytes) { - uint16_t const queued_bytes = min16_of(total_bytes, DCD_11U_13U_MAX_BYTE_PER_TD); + uint16_t const queued_bytes = tu_min16(total_bytes, DCD_11U_13U_MAX_BYTE_PER_TD); dcd_data.current_td[ep_id].queued_bytes_in_buff[buff_idx] = queued_bytes; dcd_data.current_td[ep_id].remaining_bytes -= queued_bytes; diff --git a/src/portable/nxp/lpc17xx/dcd_lpc175x_6x.c b/src/portable/nxp/lpc17xx/dcd_lpc175x_6x.c index a87e7d899..8c87984e8 100644 --- a/src/portable/nxp/lpc17xx/dcd_lpc175x_6x.c +++ b/src/portable/nxp/lpc17xx/dcd_lpc175x_6x.c @@ -312,7 +312,7 @@ static inline uint16_t length_byte2dword(uint16_t length_in_bytes) static tusb_error_t pipe_control_xfer(uint8_t ep_id, uint8_t* p_buffer, uint16_t length) { - uint16_t const packet_len = min16_of(length, CFG_TUD_ENDOINT0_SIZE); + uint16_t const packet_len = tu_min16(length, CFG_TUD_ENDOINT0_SIZE); if (ep_id) { @@ -355,7 +355,7 @@ static tusb_error_t pipe_control_read(void * buffer, uint16_t length) LPC_USB->USBCtrl = USBCTRL_READ_ENABLE_MASK; // logical endpoint = 0 while ((LPC_USB->USBRxPLen & USBRXPLEN_PACKET_READY_MASK) == 0) {} // TODO blocking, should have timeout - uint16_t actual_length = min16_of(length, (uint16_t) (LPC_USB->USBRxPLen & USBRXPLEN_PACKET_LENGTH_MASK) ); + uint16_t actual_length = tu_min16(length, (uint16_t) (LPC_USB->USBRxPLen & USBRXPLEN_PACKET_LENGTH_MASK) ); uint32_t *p_read_data = (uint32_t*) buffer; for( uint16_t count=0; count < length_byte2dword(actual_length); count++) { diff --git a/src/portable/nxp/lpc43xx_lpc18xx/dcd_lpc43xx.c b/src/portable/nxp/lpc43xx_lpc18xx/dcd_lpc43xx.c index 61f829713..792a009f2 100644 --- a/src/portable/nxp/lpc43xx_lpc18xx/dcd_lpc43xx.c +++ b/src/portable/nxp/lpc43xx_lpc18xx/dcd_lpc43xx.c @@ -209,7 +209,7 @@ static void qtd_init(dcd_qtd_t* p_qtd, void * data_ptr, uint16_t total_bytes) p_qtd->buffer[0] = (uint32_t) data_ptr; for(uint8_t i=1; i<5; i++) { - p_qtd->buffer[i] |= align4k( p_qtd->buffer[i-1] ) + 4096; + p_qtd->buffer[i] |= tu_align4k( p_qtd->buffer[i-1] ) + 4096; } } } diff --git a/tests/lpc18xx_43xx/test/host/ehci/test_ehci_init.c b/tests/lpc18xx_43xx/test/host/ehci/test_ehci_init.c index f31944338..69b7c1dd9 100644 --- a/tests/lpc18xx_43xx/test/host/ehci/test_ehci_init.c +++ b/tests/lpc18xx_43xx/test/host/ehci/test_ehci_init.c @@ -107,7 +107,7 @@ void test_hcd_init_async_list(void) TEST_ASSERT_EQUAL_HEX(async_head, regs->async_list_base); - TEST_ASSERT_EQUAL_HEX(async_head, align32( (uint32_t) async_head) ); + TEST_ASSERT_EQUAL_HEX(async_head, tu_align32( (uint32_t) async_head) ); TEST_ASSERT_EQUAL(EHCI_QUEUE_ELEMENT_QHD, async_head->next.type); TEST_ASSERT_FALSE(async_head->next.terminate); @@ -118,7 +118,7 @@ void test_hcd_init_async_list(void) void check_qhd_endpoint_link(ehci_link_t *p_prev, ehci_qhd_t *p_qhd) { //------------- period list check -------------// - TEST_ASSERT_EQUAL_HEX((uint32_t) p_qhd, align32(p_prev->address)); + TEST_ASSERT_EQUAL_HEX((uint32_t) p_qhd, tu_align32(p_prev->address)); TEST_ASSERT_FALSE(p_prev->terminate); TEST_ASSERT_EQUAL(EHCI_QUEUE_ELEMENT_QHD, p_prev->type); } diff --git a/tests/lpc18xx_43xx/test/host/ehci/test_pipe_bulk_open.c b/tests/lpc18xx_43xx/test/host/ehci/test_pipe_bulk_open.c index c2d52ce4c..a26b990d3 100644 --- a/tests/lpc18xx_43xx/test/host/ehci/test_pipe_bulk_open.c +++ b/tests/lpc18xx_43xx/test/host/ehci/test_pipe_bulk_open.c @@ -143,7 +143,7 @@ void verify_bulk_open_qhd(ehci_qhd_t *p_qhd, tusb_desc_endpoint_t const * desc_e TEST_ASSERT_EQUAL(class_code, p_qhd->class_code); //------------- async list check -------------// - TEST_ASSERT_EQUAL_HEX((uint32_t) p_qhd, align32(async_head->next.address)); + TEST_ASSERT_EQUAL_HEX((uint32_t) p_qhd, tu_align32(async_head->next.address)); TEST_ASSERT_FALSE(async_head->next.terminate); TEST_ASSERT_EQUAL(EHCI_QUEUE_ELEMENT_QHD, async_head->next.type); } @@ -164,7 +164,7 @@ void test_open_bulk_qhd_data(void) verify_bulk_open_qhd(p_qhd, desc_endpoint, TUSB_CLASS_MSC); //------------- async list check -------------// - TEST_ASSERT_EQUAL_HEX((uint32_t) p_qhd, align32(async_head->next.address)); + TEST_ASSERT_EQUAL_HEX((uint32_t) p_qhd, tu_align32(async_head->next.address)); TEST_ASSERT_FALSE(async_head->next.terminate); TEST_ASSERT_EQUAL(EHCI_QUEUE_ELEMENT_QHD, async_head->next.type); } @@ -194,7 +194,7 @@ void test_bulk_close(void) hcd_pipe_close(pipe_hdl); TEST_ASSERT(p_qhd->is_removing); - TEST_ASSERT( align32(async_head->next.address) != (uint32_t) p_qhd ); - TEST_ASSERT_EQUAL_HEX( (uint32_t) async_head, align32(p_qhd->next.address) ); + TEST_ASSERT( tu_align32(async_head->next.address) != (uint32_t) p_qhd ); + TEST_ASSERT_EQUAL_HEX( (uint32_t) async_head, tu_align32(p_qhd->next.address) ); TEST_ASSERT_EQUAL(EHCI_QUEUE_ELEMENT_QHD, p_qhd->next.type); } diff --git a/tests/lpc18xx_43xx/test/host/ehci/test_pipe_bulk_xfer.c b/tests/lpc18xx_43xx/test/host/ehci/test_pipe_bulk_xfer.c index e3d78f668..a52c721fe 100644 --- a/tests/lpc18xx_43xx/test/host/ehci/test_pipe_bulk_xfer.c +++ b/tests/lpc18xx_43xx/test/host/ehci/test_pipe_bulk_xfer.c @@ -140,7 +140,7 @@ void verify_qtd(ehci_qtd_t *p_qtd, uint8_t p_data[], uint16_t length) TEST_ASSERT_EQUAL_HEX( p_data, p_qtd->buffer[0] ); for(uint8_t i=1; i<5; i++) { - TEST_ASSERT_EQUAL_HEX( align4k((uint32_t) (p_data+4096*i)), align4k(p_qtd->buffer[i]) ); + TEST_ASSERT_EQUAL_HEX( tu_align4k((uint32_t) (p_data+4096*i)), tu_align4k(p_qtd->buffer[i]) ); } } @@ -193,7 +193,7 @@ void test_bulk_xfer_double(void) //------------- list tail -------------// TEST_ASSERT_NOT_NULL(p_tail); verify_qtd(p_tail, data2, sizeof(data2)); - TEST_ASSERT_EQUAL_HEX( align32(p_head->next.address), p_tail); + TEST_ASSERT_EQUAL_HEX( tu_align32(p_head->next.address), p_tail); TEST_ASSERT_EQUAL(EHCI_PID_IN, p_tail->pid); TEST_ASSERT_TRUE(p_tail->next.terminate); TEST_ASSERT_TRUE(p_tail->int_on_complete); diff --git a/tests/lpc18xx_43xx/test/host/ehci/test_pipe_control_open.c b/tests/lpc18xx_43xx/test/host/ehci/test_pipe_control_open.c index 1143b9faa..22cbf7569 100644 --- a/tests/lpc18xx_43xx/test/host/ehci/test_pipe_control_open.c +++ b/tests/lpc18xx_43xx/test/host/ehci/test_pipe_control_open.c @@ -142,7 +142,7 @@ void test_control_open_qhd_data(void) TEST_ASSERT_FALSE(p_control_qhd->head_list_flag); //------------- async list check -------------// - TEST_ASSERT_EQUAL_HEX((uint32_t) p_control_qhd, align32(async_head->next.address)); + TEST_ASSERT_EQUAL_HEX((uint32_t) p_control_qhd, tu_align32(async_head->next.address)); TEST_ASSERT_FALSE(async_head->next.terminate); TEST_ASSERT_EQUAL(EHCI_QUEUE_ELEMENT_QHD, async_head->next.type); } @@ -191,6 +191,6 @@ void test_control_close(void) TEST_ASSERT(p_control_qhd->is_removing); TEST_ASSERT(p_control_qhd->used); - TEST_ASSERT( align32(get_async_head(hostid)->next.address) != (uint32_t) p_control_qhd ); - TEST_ASSERT_EQUAL( get_async_head(hostid), align32(p_control_qhd->next.address)); + TEST_ASSERT( tu_align32(get_async_head(hostid)->next.address) != (uint32_t) p_control_qhd ); + TEST_ASSERT_EQUAL( get_async_head(hostid), tu_align32(p_control_qhd->next.address)); } diff --git a/tests/lpc18xx_43xx/test/host/ehci/test_pipe_interrupt_open.c b/tests/lpc18xx_43xx/test/host/ehci/test_pipe_interrupt_open.c index 1f8fc9a12..f39021ef2 100644 --- a/tests/lpc18xx_43xx/test/host/ehci/test_pipe_interrupt_open.c +++ b/tests/lpc18xx_43xx/test/host/ehci/test_pipe_interrupt_open.c @@ -136,7 +136,7 @@ void verify_int_qhd(ehci_qhd_t *p_qhd, tusb_desc_endpoint_t const * desc_endpoin void check_int_endpoint_link(ehci_qhd_t *p_prev, ehci_qhd_t *p_qhd) { //------------- period list check -------------// - TEST_ASSERT_EQUAL_HEX((uint32_t) p_qhd, align32(p_prev->next.address)); + TEST_ASSERT_EQUAL_HEX((uint32_t) p_qhd, tu_align32(p_prev->next.address)); TEST_ASSERT_FALSE(p_prev->next.terminate); TEST_ASSERT_EQUAL(EHCI_QUEUE_ELEMENT_QHD, p_prev->next.type); } @@ -181,7 +181,7 @@ void test_open_interrupt_hs_interval_2(void) p_int_qhd = &ehci_data.device[ pipe_hdl.dev_addr-1].qhd[ pipe_hdl.index ]; TEST_ASSERT_EQUAL(0 , p_int_qhd->interval_ms); - TEST_ASSERT_EQUAL(4 , cardinality_of(p_int_qhd->interrupt_smask)); // either 10101010 or 01010101 + TEST_ASSERT_EQUAL(4 , tu_cardof(p_int_qhd->interrupt_smask)); // either 10101010 or 01010101 check_int_endpoint_link(period_head_arr, p_int_qhd); } @@ -195,7 +195,7 @@ void test_open_interrupt_hs_interval_3(void) p_int_qhd = &ehci_data.device[ pipe_hdl.dev_addr-1].qhd[ pipe_hdl.index ]; TEST_ASSERT_EQUAL(0, p_int_qhd->interval_ms); - TEST_ASSERT_EQUAL(2, cardinality_of(p_int_qhd->interrupt_smask) ); + TEST_ASSERT_EQUAL(2, tu_cardof(p_int_qhd->interrupt_smask) ); check_int_endpoint_link(period_head_arr, p_int_qhd); } @@ -209,7 +209,7 @@ void test_open_interrupt_hs_interval_4(void) p_int_qhd = &ehci_data.device[ pipe_hdl.dev_addr-1].qhd[ pipe_hdl.index ]; TEST_ASSERT_EQUAL(1, p_int_qhd->interval_ms); - TEST_ASSERT_EQUAL(1, cardinality_of(p_int_qhd->interrupt_smask) ); + TEST_ASSERT_EQUAL(1, tu_cardof(p_int_qhd->interrupt_smask) ); check_int_endpoint_link(period_head_arr, p_int_qhd); } @@ -223,7 +223,7 @@ void test_open_interrupt_hs_interval_5(void) p_int_qhd = &ehci_data.device[ pipe_hdl.dev_addr-1].qhd[ pipe_hdl.index ]; TEST_ASSERT_EQUAL(2, p_int_qhd->interval_ms); - TEST_ASSERT_EQUAL(1, cardinality_of(p_int_qhd->interrupt_smask) ); + TEST_ASSERT_EQUAL(1, tu_cardof(p_int_qhd->interrupt_smask) ); check_int_endpoint_link( get_period_head(hostid, 2), p_int_qhd ); } @@ -237,7 +237,7 @@ void test_open_interrupt_hs_interval_6(void) p_int_qhd = &ehci_data.device[ pipe_hdl.dev_addr-1].qhd[ pipe_hdl.index ]; TEST_ASSERT_EQUAL(4, p_int_qhd->interval_ms); - TEST_ASSERT_EQUAL(1, cardinality_of(p_int_qhd->interrupt_smask) ); + TEST_ASSERT_EQUAL(1, tu_cardof(p_int_qhd->interrupt_smask) ); check_int_endpoint_link( get_period_head(hostid, 4), p_int_qhd); } @@ -251,7 +251,7 @@ void test_open_interrupt_hs_interval_7(void) p_int_qhd = &ehci_data.device[ pipe_hdl.dev_addr-1].qhd[ pipe_hdl.index ]; TEST_ASSERT_EQUAL(8, p_int_qhd->interval_ms); - TEST_ASSERT_EQUAL(1, cardinality_of(p_int_qhd->interrupt_smask) ); + TEST_ASSERT_EQUAL(1, tu_cardof(p_int_qhd->interrupt_smask) ); check_int_endpoint_link( get_period_head(hostid, 8), p_int_qhd); } @@ -265,7 +265,7 @@ void test_open_interrupt_hs_interval_8(void) p_int_qhd = &ehci_data.device[ pipe_hdl.dev_addr-1].qhd[ pipe_hdl.index ]; TEST_ASSERT_EQUAL(255, p_int_qhd->interval_ms); - TEST_ASSERT_EQUAL(1, cardinality_of(p_int_qhd->interrupt_smask) ); + TEST_ASSERT_EQUAL(1, tu_cardof(p_int_qhd->interrupt_smask) ); check_int_endpoint_link( get_period_head(hostid, 255), p_int_qhd); check_int_endpoint_link( get_period_head(hostid, 8) , p_int_qhd); } @@ -318,8 +318,8 @@ void test_interrupt_close(void) hcd_pipe_close(pipe_hdl) ); TEST_ASSERT(p_int_qhd->is_removing); - TEST_ASSERT( align32(period_head_arr->next.address) != (uint32_t) p_int_qhd ); - TEST_ASSERT_EQUAL_HEX( (uint32_t) period_head_arr, align32(p_int_qhd->next.address ) ); + TEST_ASSERT( tu_align32(period_head_arr->next.address) != (uint32_t) p_int_qhd ); + TEST_ASSERT_EQUAL_HEX( (uint32_t) period_head_arr, tu_align32(p_int_qhd->next.address ) ); TEST_ASSERT_EQUAL(EHCI_QUEUE_ELEMENT_QHD, p_int_qhd->next.type); } @@ -336,7 +336,7 @@ void test_interrupt_256ms_close(void) hcd_pipe_close(pipe_hdl) ); TEST_ASSERT(p_int_qhd->is_removing); - TEST_ASSERT( align32(get_period_head(hostid, 8)->address) != (uint32_t) p_int_qhd ); - TEST_ASSERT_EQUAL_HEX( (uint32_t) get_period_head(hostid, 8), align32(p_int_qhd->next.address ) ); + TEST_ASSERT( tu_align32(get_period_head(hostid, 8)->address) != (uint32_t) p_int_qhd ); + TEST_ASSERT_EQUAL_HEX( (uint32_t) get_period_head(hostid, 8), tu_align32(p_int_qhd->next.address ) ); TEST_ASSERT_EQUAL(EHCI_QUEUE_ELEMENT_QHD, p_int_qhd->next.type); } diff --git a/tests/lpc18xx_43xx/test/host/ehci/test_pipe_interrupt_xfer.c b/tests/lpc18xx_43xx/test/host/ehci/test_pipe_interrupt_xfer.c index cacc1e98c..aeb094932 100644 --- a/tests/lpc18xx_43xx/test/host/ehci/test_pipe_interrupt_xfer.c +++ b/tests/lpc18xx_43xx/test/host/ehci/test_pipe_interrupt_xfer.c @@ -142,7 +142,7 @@ void verify_qtd(ehci_qtd_t *p_qtd, uint8_t p_data[], uint16_t length) TEST_ASSERT_EQUAL_HEX( p_data, p_qtd->buffer[0] ); for(uint8_t i=1; i<5; i++) { - TEST_ASSERT_EQUAL_HEX( align4k((uint32_t) (p_data+4096*i)), align4k(p_qtd->buffer[i]) ); + TEST_ASSERT_EQUAL_HEX( tu_align4k((uint32_t) (p_data+4096*i)), tu_align4k(p_qtd->buffer[i]) ); } } @@ -182,7 +182,7 @@ void test_interrupt_xfer_double(void) //------------- list tail -------------// TEST_ASSERT_NOT_NULL(p_tail); verify_qtd(p_tail, data2, sizeof(data2)); - TEST_ASSERT_EQUAL_HEX( align32(p_head->next.address), p_tail); + TEST_ASSERT_EQUAL_HEX( tu_align32(p_head->next.address), p_tail); TEST_ASSERT_EQUAL(EHCI_PID_IN, p_tail->pid); TEST_ASSERT_TRUE(p_tail->next.terminate); TEST_ASSERT_TRUE(p_tail->int_on_complete); diff --git a/tests/support/ehci_controller_fake.c b/tests/support/ehci_controller_fake.c index 04d55172c..041e1dbb5 100644 --- a/tests/support/ehci_controller_fake.c +++ b/tests/support/ehci_controller_fake.c @@ -95,7 +95,7 @@ void complete_qtd_in_qhd(ehci_qhd_t *p_qhd) { while(!p_qhd->qtd_overlay.next.terminate) { - ehci_qtd_t* p_qtd = (ehci_qtd_t*) align32(p_qhd->qtd_overlay.next.address); + ehci_qtd_t* p_qtd = (ehci_qtd_t*) tu_align32(p_qhd->qtd_overlay.next.address); p_qtd->active = 0; p_qtd->total_bytes = 0; p_qhd->qtd_overlay = *p_qtd; @@ -110,7 +110,7 @@ bool complete_all_qtd_in_async(ehci_qhd_t *head) do { complete_qtd_in_qhd(p_qhd); - p_qhd = (ehci_qhd_t*) align32(p_qhd->next.address); + p_qhd = (ehci_qhd_t*) tu_align32(p_qhd->next.address); }while(p_qhd != head); // stop if loop around return true; @@ -121,7 +121,7 @@ bool complete_all_qtd_in_period(ehci_link_t *head) while(!head->terminate) { uint32_t queue_type = head->type; - head = (ehci_link_t*) align32(head->address); + head = (ehci_link_t*) tu_align32(head->address); if ( queue_type == EHCI_QUEUE_ELEMENT_QHD) { @@ -153,7 +153,7 @@ void complete_1st_qtd_with_error(ehci_qhd_t* p_qhd, bool halted, bool xact_err) { if(!p_qhd->qtd_overlay.next.terminate) // TODO add active check { - ehci_qtd_t* p_qtd = (ehci_qtd_t*) align32(p_qhd->qtd_overlay.next.address); + ehci_qtd_t* p_qtd = (ehci_qtd_t*) tu_align32(p_qhd->qtd_overlay.next.address); p_qtd->active = 0; p_qtd->halted = halted ? 1 : 0; p_qtd->xact_err = xact_err ? 1 : 0; @@ -172,7 +172,7 @@ void complete_list_with_error(uint8_t hostid, bool halted, bool xact_err) do { complete_1st_qtd_with_error(p_qhd, halted, xact_err); - p_qhd = (ehci_qhd_t*) align32(p_qhd->next.address); + p_qhd = (ehci_qhd_t*) tu_align32(p_qhd->next.address); }while(p_qhd != get_async_head(hostid)); // stop if loop around //------------- Period List -------------// @@ -183,7 +183,7 @@ void complete_list_with_error(uint8_t hostid, bool halted, bool xact_err) while(!head->terminate) { uint32_t queue_type = head->type; - head = (ehci_link_t*) align32(head->address); + head = (ehci_link_t*) tu_align32(head->address); if ( queue_type == EHCI_QUEUE_ELEMENT_QHD) { diff --git a/tests/support/type_helper.h b/tests/support/type_helper.h index d0712e4f0..3e27cef2e 100644 --- a/tests/support/type_helper.h +++ b/tests/support/type_helper.h @@ -70,7 +70,7 @@ #define TEST_ASSERT_STATUS( actual )\ TEST_ASSERT_EQUAL( TUSB_ERROR_NONE, (actual) ) -// log2_of a value is equivalent to its highest set bit's position +// tu_log2 a value is equivalent to its highest set bit's position #define BITFIELD_OFFSET_OF_MEMBER(struct_type, member, bitfield_member) \ ({\ uint32_t value=0;\ @@ -78,7 +78,7 @@ memclr_((void*)&str, sizeof(struct_type));\ str.member.bitfield_member = 1;\ memcpy(&value, (void*)&str.member, sizeof(str.member));\ - log2_of( value );\ + tu_log2( value );\ }) #define BITFIELD_OFFSET_OF_UINT32(struct_type, offset, bitfield_member) \ @@ -86,7 +86,7 @@ struct_type str;\ memclr_(&str, sizeof(struct_type));\ str.bitfield_member = 1;\ - log2_of( ((uint32_t*) &str)[offset] );\ + tu_log2( ((uint32_t*) &str)[offset] );\ }) #ifdef __cplusplus -- cgit v1.3.1 From 460285f852c63fa835df8eea32a9f10814f013a5 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 23 Aug 2018 21:05:52 +0700 Subject: fix compiler static assert complain --- src/common/tusb_compiler.h | 1 + 1 file changed, 1 insertion(+) (limited to 'src/common') diff --git a/src/common/tusb_compiler.h b/src/common/tusb_compiler.h index 09cc59633..7048732cf 100644 --- a/src/common/tusb_compiler.h +++ b/src/common/tusb_compiler.h @@ -59,6 +59,7 @@ // Compile-time Assert (use TU_VERIFY_STATIC to avoid name conflict) //--------------------------------------------------------------------+ #if defined(__ICCARM__) || (__STDC_VERSION__ >= 201112L ) + #include #define TU_VERIFY_STATIC static_assert #else #define TU_VERIFY_STATIC(const_expr, _mess) enum { XSTRING_CONCAT_(_verify_static_, _TU_COUNTER_) = 1/(!!(const_expr)) } -- cgit v1.3.1 From 1a4a27324b1ed5adc456a1df72f34b63b9b87c93 Mon Sep 17 00:00:00 2001 From: hathach Date: Sun, 2 Sep 2018 20:30:07 +0700 Subject: clean up --- pkg.yml | 9 +++++++++ src/common/tusb_compiler.h | 5 ++--- version.yml | 2 -- 3 files changed, 11 insertions(+), 5 deletions(-) create mode 100644 pkg.yml (limited to 'src/common') diff --git a/pkg.yml b/pkg.yml new file mode 100644 index 000000000..3b3e10796 --- /dev/null +++ b/pkg.yml @@ -0,0 +1,9 @@ +pkg.name: tinyusb +pkg.description: A silly USB stack for embedded +pkg.author: "Ha Thach " +pkg.homepage: "https://github.com/hathach/tinyusb" +pkg.keywords: + - usb + +pkg.deps: + - "@apache-mynewt-core/kernel/os" diff --git a/src/common/tusb_compiler.h b/src/common/tusb_compiler.h index 7048732cf..933d76043 100644 --- a/src/common/tusb_compiler.h +++ b/src/common/tusb_compiler.h @@ -58,9 +58,8 @@ //--------------------------------------------------------------------+ // Compile-time Assert (use TU_VERIFY_STATIC to avoid name conflict) //--------------------------------------------------------------------+ -#if defined(__ICCARM__) || (__STDC_VERSION__ >= 201112L ) - #include - #define TU_VERIFY_STATIC static_assert +#if __STDC_VERSION__ >= 201112L + #define TU_VERIFY_STATIC _Static_assert #else #define TU_VERIFY_STATIC(const_expr, _mess) enum { XSTRING_CONCAT_(_verify_static_, _TU_COUNTER_) = 1/(!!(const_expr)) } #endif diff --git a/version.yml b/version.yml index b6495858d..92baae6de 100644 --- a/version.yml +++ b/version.yml @@ -1,3 +1 @@ -# Newt uses this file to determine the version of a checked out repo. -# This should always be 0.0.0 in the master branch. repo.version: 0.0.1 -- cgit v1.3.1 From c78540be0f3c97cc642af7d4d5d82eb018557f9b Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 26 Sep 2018 01:39:59 +0700 Subject: add sys/queue.h to common --- src/common/queue.h | 871 +++++++++++++++++++++++++++++++++++++++++++++++++ src/common/tusb_fifo.c | 30 +- 2 files changed, 876 insertions(+), 25 deletions(-) create mode 100644 src/common/queue.h (limited to 'src/common') diff --git a/src/common/queue.h b/src/common/queue.h new file mode 100644 index 000000000..767f43fed --- /dev/null +++ b/src/common/queue.h @@ -0,0 +1,871 @@ +/*- + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)queue.h 8.5 (Berkeley) 8/20/94 + * $FreeBSD$ + */ + +#ifndef _SYS_QUEUE_H_ +#define _SYS_QUEUE_H_ + +#include + +/* + * This file defines four types of data structures: singly-linked lists, + * singly-linked tail queues, lists and tail queues. + * + * A singly-linked list is headed by a single forward pointer. The elements + * are singly linked for minimum space and pointer manipulation overhead at + * the expense of O(n) removal for arbitrary elements. New elements can be + * added to the list after an existing element or at the head of the list. + * Elements being removed from the head of the list should use the explicit + * macro for this purpose for optimum efficiency. A singly-linked list may + * only be traversed in the forward direction. Singly-linked lists are ideal + * for applications with large datasets and few or no removals or for + * implementing a LIFO queue. + * + * A singly-linked tail queue is headed by a pair of pointers, one to the + * head of the list and the other to the tail of the list. The elements are + * singly linked for minimum space and pointer manipulation overhead at the + * expense of O(n) removal for arbitrary elements. New elements can be added + * to the list after an existing element, at the head of the list, or at the + * end of the list. Elements being removed from the head of the tail queue + * should use the explicit macro for this purpose for optimum efficiency. + * A singly-linked tail queue may only be traversed in the forward direction. + * Singly-linked tail queues are ideal for applications with large datasets + * and few or no removals or for implementing a FIFO queue. + * + * A list is headed by a single forward pointer (or an array of forward + * pointers for a hash table header). The elements are doubly linked + * so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list before + * or after an existing element or at the head of the list. A list + * may be traversed in either direction. + * + * A tail queue is headed by a pair of pointers, one to the head of the + * list and the other to the tail of the list. The elements are doubly + * linked so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list before or + * after an existing element, at the head of the list, or at the end of + * the list. A tail queue may be traversed in either direction. + * + * For details on the use of these macros, see the queue(3) manual page. + * + * Below is a summary of implemented functions where: + * + means the macro is available + * - means the macro is not available + * s means the macro is available but is slow (runs in O(n) time) + * + * SLIST LIST STAILQ TAILQ + * _HEAD + + + + + * _CLASS_HEAD + + + + + * _HEAD_INITIALIZER + + + + + * _ENTRY + + + + + * _CLASS_ENTRY + + + + + * _INIT + + + + + * _EMPTY + + + + + * _FIRST + + + + + * _NEXT + + + + + * _PREV - + - + + * _LAST - - + + + * _LAST_FAST - - - + + * _FOREACH + + + + + * _FOREACH_FROM + + + + + * _FOREACH_SAFE + + + + + * _FOREACH_FROM_SAFE + + + + + * _FOREACH_REVERSE - - - + + * _FOREACH_REVERSE_FROM - - - + + * _FOREACH_REVERSE_SAFE - - - + + * _FOREACH_REVERSE_FROM_SAFE - - - + + * _INSERT_HEAD + + + + + * _INSERT_BEFORE - + - + + * _INSERT_AFTER + + + + + * _INSERT_TAIL - - + + + * _CONCAT s s + + + * _REMOVE_AFTER + - + - + * _REMOVE_HEAD + - + - + * _REMOVE s + s + + * _SWAP + + + + + * + */ +#ifdef QUEUE_MACRO_DEBUG +#warn Use QUEUE_MACRO_DEBUG_TRACE and/or QUEUE_MACRO_DEBUG_TRASH +#define QUEUE_MACRO_DEBUG_TRACE +#define QUEUE_MACRO_DEBUG_TRASH +#endif + +#ifdef QUEUE_MACRO_DEBUG_TRACE +/* Store the last 2 places the queue element or head was altered */ +struct qm_trace { + unsigned long lastline; + unsigned long prevline; + const char *lastfile; + const char *prevfile; +}; + +#define TRACEBUF struct qm_trace trace; +#define TRACEBUF_INITIALIZER { __LINE__, 0, __FILE__, NULL } , + +#define QMD_TRACE_HEAD(head) do { \ + (head)->trace.prevline = (head)->trace.lastline; \ + (head)->trace.prevfile = (head)->trace.lastfile; \ + (head)->trace.lastline = __LINE__; \ + (head)->trace.lastfile = __FILE__; \ +} while (0) + +#define QMD_TRACE_ELEM(elem) do { \ + (elem)->trace.prevline = (elem)->trace.lastline; \ + (elem)->trace.prevfile = (elem)->trace.lastfile; \ + (elem)->trace.lastline = __LINE__; \ + (elem)->trace.lastfile = __FILE__; \ +} while (0) + +#else /* !QUEUE_MACRO_DEBUG_TRACE */ +#define QMD_TRACE_ELEM(elem) +#define QMD_TRACE_HEAD(head) +#define TRACEBUF +#define TRACEBUF_INITIALIZER +#endif /* QUEUE_MACRO_DEBUG_TRACE */ + +#ifdef QUEUE_MACRO_DEBUG_TRASH +#define TRASHIT(x) do {(x) = (void *)-1;} while (0) +#define QMD_IS_TRASHED(x) ((x) == (void *)(intptr_t)-1) +#else /* !QUEUE_MACRO_DEBUG_TRASH */ +#define TRASHIT(x) +#define QMD_IS_TRASHED(x) 0 +#endif /* QUEUE_MACRO_DEBUG_TRASH */ + +#if defined(QUEUE_MACRO_DEBUG_TRACE) || defined(QUEUE_MACRO_DEBUG_TRASH) +#define QMD_SAVELINK(name, link) void **name = (void *)&(link) +#else /* !QUEUE_MACRO_DEBUG_TRACE && !QUEUE_MACRO_DEBUG_TRASH */ +#define QMD_SAVELINK(name, link) +#endif /* QUEUE_MACRO_DEBUG_TRACE || QUEUE_MACRO_DEBUG_TRASH */ + +#ifdef __cplusplus +/* + * In C++ there can be structure lists and class lists: + */ +#define QUEUE_TYPEOF(type) type +#else +#define QUEUE_TYPEOF(type) struct type +#endif + +/* + * Singly-linked List declarations. + */ +#define SLIST_HEAD(name, type) \ +struct name { \ + struct type *slh_first; /* first element */ \ +} + +#define SLIST_CLASS_HEAD(name, type) \ +struct name { \ + class type *slh_first; /* first element */ \ +} + +#define SLIST_HEAD_INITIALIZER(head) \ + { NULL } + +#define SLIST_ENTRY(type) \ +struct { \ + struct type *sle_next; /* next element */ \ +} + +#define SLIST_CLASS_ENTRY(type) \ +struct { \ + class type *sle_next; /* next element */ \ +} + +/* + * Singly-linked List functions. + */ +#if (defined(_KERNEL) && defined(INVARIANTS)) +#define QMD_SLIST_CHECK_PREVPTR(prevp, elm) do { \ + if (*(prevp) != (elm)) \ + panic("Bad prevptr *(%p) == %p != %p", \ + (prevp), *(prevp), (elm)); \ +} while (0) +#else +#define QMD_SLIST_CHECK_PREVPTR(prevp, elm) +#endif + +#define SLIST_CONCAT(head1, head2, type, field) do { \ + QUEUE_TYPEOF(type) *curelm = SLIST_FIRST(head1); \ + if (curelm == NULL) { \ + if ((SLIST_FIRST(head1) = SLIST_FIRST(head2)) != NULL) \ + SLIST_INIT(head2); \ + } else if (SLIST_FIRST(head2) != NULL) { \ + while (SLIST_NEXT(curelm, field) != NULL) \ + curelm = SLIST_NEXT(curelm, field); \ + SLIST_NEXT(curelm, field) = SLIST_FIRST(head2); \ + SLIST_INIT(head2); \ + } \ +} while (0) + +#define SLIST_EMPTY(head) ((head)->slh_first == NULL) + +#define SLIST_FIRST(head) ((head)->slh_first) + +#define SLIST_FOREACH(var, head, field) \ + for ((var) = SLIST_FIRST((head)); \ + (var); \ + (var) = SLIST_NEXT((var), field)) + +#define SLIST_FOREACH_FROM(var, head, field) \ + for ((var) = ((var) ? (var) : SLIST_FIRST((head))); \ + (var); \ + (var) = SLIST_NEXT((var), field)) + +#define SLIST_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = SLIST_FIRST((head)); \ + (var) && ((tvar) = SLIST_NEXT((var), field), 1); \ + (var) = (tvar)) + +#define SLIST_FOREACH_FROM_SAFE(var, head, field, tvar) \ + for ((var) = ((var) ? (var) : SLIST_FIRST((head))); \ + (var) && ((tvar) = SLIST_NEXT((var), field), 1); \ + (var) = (tvar)) + +#define SLIST_FOREACH_PREVPTR(var, varp, head, field) \ + for ((varp) = &SLIST_FIRST((head)); \ + ((var) = *(varp)) != NULL; \ + (varp) = &SLIST_NEXT((var), field)) + +#define SLIST_INIT(head) do { \ + SLIST_FIRST((head)) = NULL; \ +} while (0) + +#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \ + SLIST_NEXT((elm), field) = SLIST_NEXT((slistelm), field); \ + SLIST_NEXT((slistelm), field) = (elm); \ +} while (0) + +#define SLIST_INSERT_HEAD(head, elm, field) do { \ + SLIST_NEXT((elm), field) = SLIST_FIRST((head)); \ + SLIST_FIRST((head)) = (elm); \ +} while (0) + +#define SLIST_NEXT(elm, field) ((elm)->field.sle_next) + +#define SLIST_REMOVE(head, elm, type, field) do { \ + QMD_SAVELINK(oldnext, (elm)->field.sle_next); \ + if (SLIST_FIRST((head)) == (elm)) { \ + SLIST_REMOVE_HEAD((head), field); \ + } \ + else { \ + QUEUE_TYPEOF(type) *curelm = SLIST_FIRST(head); \ + while (SLIST_NEXT(curelm, field) != (elm)) \ + curelm = SLIST_NEXT(curelm, field); \ + SLIST_REMOVE_AFTER(curelm, field); \ + } \ + TRASHIT(*oldnext); \ +} while (0) + +#define SLIST_REMOVE_AFTER(elm, field) do { \ + SLIST_NEXT(elm, field) = \ + SLIST_NEXT(SLIST_NEXT(elm, field), field); \ +} while (0) + +#define SLIST_REMOVE_HEAD(head, field) do { \ + SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field); \ +} while (0) + +#define SLIST_REMOVE_PREVPTR(prevp, elm, field) do { \ + QMD_SLIST_CHECK_PREVPTR(prevp, elm); \ + *(prevp) = SLIST_NEXT(elm, field); \ + TRASHIT((elm)->field.sle_next); \ +} while (0) + +#define SLIST_SWAP(head1, head2, type) do { \ + QUEUE_TYPEOF(type) *swap_first = SLIST_FIRST(head1); \ + SLIST_FIRST(head1) = SLIST_FIRST(head2); \ + SLIST_FIRST(head2) = swap_first; \ +} while (0) + +/* + * Singly-linked Tail queue declarations. + */ +#define STAILQ_HEAD(name, type) \ +struct name { \ + struct type *stqh_first;/* first element */ \ + struct type **stqh_last;/* addr of last next element */ \ +} + +#define STAILQ_CLASS_HEAD(name, type) \ +struct name { \ + class type *stqh_first; /* first element */ \ + class type **stqh_last; /* addr of last next element */ \ +} + +#define STAILQ_HEAD_INITIALIZER(head) \ + { NULL, &(head).stqh_first } + +#define STAILQ_ENTRY(type) \ +struct { \ + struct type *stqe_next; /* next element */ \ +} + +#define STAILQ_CLASS_ENTRY(type) \ +struct { \ + class type *stqe_next; /* next element */ \ +} + +/* + * Singly-linked Tail queue functions. + */ +#define STAILQ_CONCAT(head1, head2) do { \ + if (!STAILQ_EMPTY((head2))) { \ + *(head1)->stqh_last = (head2)->stqh_first; \ + (head1)->stqh_last = (head2)->stqh_last; \ + STAILQ_INIT((head2)); \ + } \ +} while (0) + +#define STAILQ_EMPTY(head) ((head)->stqh_first == NULL) + +#define STAILQ_FIRST(head) ((head)->stqh_first) + +#define STAILQ_FOREACH(var, head, field) \ + for((var) = STAILQ_FIRST((head)); \ + (var); \ + (var) = STAILQ_NEXT((var), field)) + +#define STAILQ_FOREACH_FROM(var, head, field) \ + for ((var) = ((var) ? (var) : STAILQ_FIRST((head))); \ + (var); \ + (var) = STAILQ_NEXT((var), field)) + +#define STAILQ_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = STAILQ_FIRST((head)); \ + (var) && ((tvar) = STAILQ_NEXT((var), field), 1); \ + (var) = (tvar)) + +#define STAILQ_FOREACH_FROM_SAFE(var, head, field, tvar) \ + for ((var) = ((var) ? (var) : STAILQ_FIRST((head))); \ + (var) && ((tvar) = STAILQ_NEXT((var), field), 1); \ + (var) = (tvar)) + +#define STAILQ_INIT(head) do { \ + STAILQ_FIRST((head)) = NULL; \ + (head)->stqh_last = &STAILQ_FIRST((head)); \ +} while (0) + +#define STAILQ_INSERT_AFTER(head, tqelm, elm, field) do { \ + if ((STAILQ_NEXT((elm), field) = STAILQ_NEXT((tqelm), field)) == NULL)\ + (head)->stqh_last = &STAILQ_NEXT((elm), field); \ + STAILQ_NEXT((tqelm), field) = (elm); \ +} while (0) + +#define STAILQ_INSERT_HEAD(head, elm, field) do { \ + if ((STAILQ_NEXT((elm), field) = STAILQ_FIRST((head))) == NULL) \ + (head)->stqh_last = &STAILQ_NEXT((elm), field); \ + STAILQ_FIRST((head)) = (elm); \ +} while (0) + +#define STAILQ_INSERT_TAIL(head, elm, field) do { \ + STAILQ_NEXT((elm), field) = NULL; \ + *(head)->stqh_last = (elm); \ + (head)->stqh_last = &STAILQ_NEXT((elm), field); \ +} while (0) + +#define STAILQ_LAST(head, type, field) \ + (STAILQ_EMPTY((head)) ? NULL : \ + __containerof((head)->stqh_last, \ + QUEUE_TYPEOF(type), field.stqe_next)) + +#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next) + +#define STAILQ_REMOVE(head, elm, type, field) do { \ + QMD_SAVELINK(oldnext, (elm)->field.stqe_next); \ + if (STAILQ_FIRST((head)) == (elm)) { \ + STAILQ_REMOVE_HEAD((head), field); \ + } \ + else { \ + QUEUE_TYPEOF(type) *curelm = STAILQ_FIRST(head); \ + while (STAILQ_NEXT(curelm, field) != (elm)) \ + curelm = STAILQ_NEXT(curelm, field); \ + STAILQ_REMOVE_AFTER(head, curelm, field); \ + } \ + TRASHIT(*oldnext); \ +} while (0) + +#define STAILQ_REMOVE_AFTER(head, elm, field) do { \ + if ((STAILQ_NEXT(elm, field) = \ + STAILQ_NEXT(STAILQ_NEXT(elm, field), field)) == NULL) \ + (head)->stqh_last = &STAILQ_NEXT((elm), field); \ +} while (0) + +#define STAILQ_REMOVE_HEAD(head, field) do { \ + if ((STAILQ_FIRST((head)) = \ + STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL) \ + (head)->stqh_last = &STAILQ_FIRST((head)); \ +} while (0) + +#define STAILQ_SWAP(head1, head2, type) do { \ + QUEUE_TYPEOF(type) *swap_first = STAILQ_FIRST(head1); \ + QUEUE_TYPEOF(type) **swap_last = (head1)->stqh_last; \ + STAILQ_FIRST(head1) = STAILQ_FIRST(head2); \ + (head1)->stqh_last = (head2)->stqh_last; \ + STAILQ_FIRST(head2) = swap_first; \ + (head2)->stqh_last = swap_last; \ + if (STAILQ_EMPTY(head1)) \ + (head1)->stqh_last = &STAILQ_FIRST(head1); \ + if (STAILQ_EMPTY(head2)) \ + (head2)->stqh_last = &STAILQ_FIRST(head2); \ +} while (0) + + +/* + * List declarations. + */ +#define LIST_HEAD(name, type) \ +struct name { \ + struct type *lh_first; /* first element */ \ +} + +#define LIST_CLASS_HEAD(name, type) \ +struct name { \ + class type *lh_first; /* first element */ \ +} + +#define LIST_HEAD_INITIALIZER(head) \ + { NULL } + +#define LIST_ENTRY(type) \ +struct { \ + struct type *le_next; /* next element */ \ + struct type **le_prev; /* address of previous next element */ \ +} + +#define LIST_CLASS_ENTRY(type) \ +struct { \ + class type *le_next; /* next element */ \ + class type **le_prev; /* address of previous next element */ \ +} + +/* + * List functions. + */ + +#if (defined(_KERNEL) && defined(INVARIANTS)) +/* + * QMD_LIST_CHECK_HEAD(LIST_HEAD *head, LIST_ENTRY NAME) + * + * If the list is non-empty, validates that the first element of the list + * points back at 'head.' + */ +#define QMD_LIST_CHECK_HEAD(head, field) do { \ + if (LIST_FIRST((head)) != NULL && \ + LIST_FIRST((head))->field.le_prev != \ + &LIST_FIRST((head))) \ + panic("Bad list head %p first->prev != head", (head)); \ +} while (0) + +/* + * QMD_LIST_CHECK_NEXT(TYPE *elm, LIST_ENTRY NAME) + * + * If an element follows 'elm' in the list, validates that the next element + * points back at 'elm.' + */ +#define QMD_LIST_CHECK_NEXT(elm, field) do { \ + if (LIST_NEXT((elm), field) != NULL && \ + LIST_NEXT((elm), field)->field.le_prev != \ + &((elm)->field.le_next)) \ + panic("Bad link elm %p next->prev != elm", (elm)); \ +} while (0) + +/* + * QMD_LIST_CHECK_PREV(TYPE *elm, LIST_ENTRY NAME) + * + * Validates that the previous element (or head of the list) points to 'elm.' + */ +#define QMD_LIST_CHECK_PREV(elm, field) do { \ + if (*(elm)->field.le_prev != (elm)) \ + panic("Bad link elm %p prev->next != elm", (elm)); \ +} while (0) +#else +#define QMD_LIST_CHECK_HEAD(head, field) +#define QMD_LIST_CHECK_NEXT(elm, field) +#define QMD_LIST_CHECK_PREV(elm, field) +#endif /* (_KERNEL && INVARIANTS) */ + +#define LIST_CONCAT(head1, head2, type, field) do { \ + QUEUE_TYPEOF(type) *curelm = LIST_FIRST(head1); \ + if (curelm == NULL) { \ + if ((LIST_FIRST(head1) = LIST_FIRST(head2)) != NULL) { \ + LIST_FIRST(head2)->field.le_prev = \ + &LIST_FIRST((head1)); \ + LIST_INIT(head2); \ + } \ + } else if (LIST_FIRST(head2) != NULL) { \ + while (LIST_NEXT(curelm, field) != NULL) \ + curelm = LIST_NEXT(curelm, field); \ + LIST_NEXT(curelm, field) = LIST_FIRST(head2); \ + LIST_FIRST(head2)->field.le_prev = &LIST_NEXT(curelm, field); \ + LIST_INIT(head2); \ + } \ +} while (0) + +#define LIST_EMPTY(head) ((head)->lh_first == NULL) + +#define LIST_FIRST(head) ((head)->lh_first) + +#define LIST_FOREACH(var, head, field) \ + for ((var) = LIST_FIRST((head)); \ + (var); \ + (var) = LIST_NEXT((var), field)) + +#define LIST_FOREACH_FROM(var, head, field) \ + for ((var) = ((var) ? (var) : LIST_FIRST((head))); \ + (var); \ + (var) = LIST_NEXT((var), field)) + +#define LIST_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = LIST_FIRST((head)); \ + (var) && ((tvar) = LIST_NEXT((var), field), 1); \ + (var) = (tvar)) + +#define LIST_FOREACH_FROM_SAFE(var, head, field, tvar) \ + for ((var) = ((var) ? (var) : LIST_FIRST((head))); \ + (var) && ((tvar) = LIST_NEXT((var), field), 1); \ + (var) = (tvar)) + +#define LIST_INIT(head) do { \ + LIST_FIRST((head)) = NULL; \ +} while (0) + +#define LIST_INSERT_AFTER(listelm, elm, field) do { \ + QMD_LIST_CHECK_NEXT(listelm, field); \ + if ((LIST_NEXT((elm), field) = LIST_NEXT((listelm), field)) != NULL)\ + LIST_NEXT((listelm), field)->field.le_prev = \ + &LIST_NEXT((elm), field); \ + LIST_NEXT((listelm), field) = (elm); \ + (elm)->field.le_prev = &LIST_NEXT((listelm), field); \ +} while (0) + +#define LIST_INSERT_BEFORE(listelm, elm, field) do { \ + QMD_LIST_CHECK_PREV(listelm, field); \ + (elm)->field.le_prev = (listelm)->field.le_prev; \ + LIST_NEXT((elm), field) = (listelm); \ + *(listelm)->field.le_prev = (elm); \ + (listelm)->field.le_prev = &LIST_NEXT((elm), field); \ +} while (0) + +#define LIST_INSERT_HEAD(head, elm, field) do { \ + QMD_LIST_CHECK_HEAD((head), field); \ + if ((LIST_NEXT((elm), field) = LIST_FIRST((head))) != NULL) \ + LIST_FIRST((head))->field.le_prev = &LIST_NEXT((elm), field);\ + LIST_FIRST((head)) = (elm); \ + (elm)->field.le_prev = &LIST_FIRST((head)); \ +} while (0) + +#define LIST_NEXT(elm, field) ((elm)->field.le_next) + +#define LIST_PREV(elm, head, type, field) \ + ((elm)->field.le_prev == &LIST_FIRST((head)) ? NULL : \ + __containerof((elm)->field.le_prev, \ + QUEUE_TYPEOF(type), field.le_next)) + +#define LIST_REMOVE(elm, field) do { \ + QMD_SAVELINK(oldnext, (elm)->field.le_next); \ + QMD_SAVELINK(oldprev, (elm)->field.le_prev); \ + QMD_LIST_CHECK_NEXT(elm, field); \ + QMD_LIST_CHECK_PREV(elm, field); \ + if (LIST_NEXT((elm), field) != NULL) \ + LIST_NEXT((elm), field)->field.le_prev = \ + (elm)->field.le_prev; \ + *(elm)->field.le_prev = LIST_NEXT((elm), field); \ + TRASHIT(*oldnext); \ + TRASHIT(*oldprev); \ +} while (0) + +#define LIST_SWAP(head1, head2, type, field) do { \ + QUEUE_TYPEOF(type) *swap_tmp = LIST_FIRST(head1); \ + LIST_FIRST((head1)) = LIST_FIRST((head2)); \ + LIST_FIRST((head2)) = swap_tmp; \ + if ((swap_tmp = LIST_FIRST((head1))) != NULL) \ + swap_tmp->field.le_prev = &LIST_FIRST((head1)); \ + if ((swap_tmp = LIST_FIRST((head2))) != NULL) \ + swap_tmp->field.le_prev = &LIST_FIRST((head2)); \ +} while (0) + +/* + * Tail queue declarations. + */ +#define TAILQ_HEAD(name, type) \ +struct name { \ + struct type *tqh_first; /* first element */ \ + struct type **tqh_last; /* addr of last next element */ \ + TRACEBUF \ +} + +#define TAILQ_CLASS_HEAD(name, type) \ +struct name { \ + class type *tqh_first; /* first element */ \ + class type **tqh_last; /* addr of last next element */ \ + TRACEBUF \ +} + +#define TAILQ_HEAD_INITIALIZER(head) \ + { NULL, &(head).tqh_first, TRACEBUF_INITIALIZER } + +#define TAILQ_ENTRY(type) \ +struct { \ + struct type *tqe_next; /* next element */ \ + struct type **tqe_prev; /* address of previous next element */ \ + TRACEBUF \ +} + +#define TAILQ_CLASS_ENTRY(type) \ +struct { \ + class type *tqe_next; /* next element */ \ + class type **tqe_prev; /* address of previous next element */ \ + TRACEBUF \ +} + +/* + * Tail queue functions. + */ +#if (defined(_KERNEL) && defined(INVARIANTS)) +/* + * QMD_TAILQ_CHECK_HEAD(TAILQ_HEAD *head, TAILQ_ENTRY NAME) + * + * If the tailq is non-empty, validates that the first element of the tailq + * points back at 'head.' + */ +#define QMD_TAILQ_CHECK_HEAD(head, field) do { \ + if (!TAILQ_EMPTY(head) && \ + TAILQ_FIRST((head))->field.tqe_prev != \ + &TAILQ_FIRST((head))) \ + panic("Bad tailq head %p first->prev != head", (head)); \ +} while (0) + +/* + * QMD_TAILQ_CHECK_TAIL(TAILQ_HEAD *head, TAILQ_ENTRY NAME) + * + * Validates that the tail of the tailq is a pointer to pointer to NULL. + */ +#define QMD_TAILQ_CHECK_TAIL(head, field) do { \ + if (*(head)->tqh_last != NULL) \ + panic("Bad tailq NEXT(%p->tqh_last) != NULL", (head)); \ +} while (0) + +/* + * QMD_TAILQ_CHECK_NEXT(TYPE *elm, TAILQ_ENTRY NAME) + * + * If an element follows 'elm' in the tailq, validates that the next element + * points back at 'elm.' + */ +#define QMD_TAILQ_CHECK_NEXT(elm, field) do { \ + if (TAILQ_NEXT((elm), field) != NULL && \ + TAILQ_NEXT((elm), field)->field.tqe_prev != \ + &((elm)->field.tqe_next)) \ + panic("Bad link elm %p next->prev != elm", (elm)); \ +} while (0) + +/* + * QMD_TAILQ_CHECK_PREV(TYPE *elm, TAILQ_ENTRY NAME) + * + * Validates that the previous element (or head of the tailq) points to 'elm.' + */ +#define QMD_TAILQ_CHECK_PREV(elm, field) do { \ + if (*(elm)->field.tqe_prev != (elm)) \ + panic("Bad link elm %p prev->next != elm", (elm)); \ +} while (0) +#else +#define QMD_TAILQ_CHECK_HEAD(head, field) +#define QMD_TAILQ_CHECK_TAIL(head, headname) +#define QMD_TAILQ_CHECK_NEXT(elm, field) +#define QMD_TAILQ_CHECK_PREV(elm, field) +#endif /* (_KERNEL && INVARIANTS) */ + +#define TAILQ_CONCAT(head1, head2, field) do { \ + if (!TAILQ_EMPTY(head2)) { \ + *(head1)->tqh_last = (head2)->tqh_first; \ + (head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \ + (head1)->tqh_last = (head2)->tqh_last; \ + TAILQ_INIT((head2)); \ + QMD_TRACE_HEAD(head1); \ + QMD_TRACE_HEAD(head2); \ + } \ +} while (0) + +#define TAILQ_EMPTY(head) ((head)->tqh_first == NULL) + +#define TAILQ_FIRST(head) ((head)->tqh_first) + +#define TAILQ_FOREACH(var, head, field) \ + for ((var) = TAILQ_FIRST((head)); \ + (var); \ + (var) = TAILQ_NEXT((var), field)) + +#define TAILQ_FOREACH_FROM(var, head, field) \ + for ((var) = ((var) ? (var) : TAILQ_FIRST((head))); \ + (var); \ + (var) = TAILQ_NEXT((var), field)) + +#define TAILQ_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = TAILQ_FIRST((head)); \ + (var) && ((tvar) = TAILQ_NEXT((var), field), 1); \ + (var) = (tvar)) + +#define TAILQ_FOREACH_FROM_SAFE(var, head, field, tvar) \ + for ((var) = ((var) ? (var) : TAILQ_FIRST((head))); \ + (var) && ((tvar) = TAILQ_NEXT((var), field), 1); \ + (var) = (tvar)) + +#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \ + for ((var) = TAILQ_LAST((head), headname); \ + (var); \ + (var) = TAILQ_PREV((var), headname, field)) + +#define TAILQ_FOREACH_REVERSE_FROM(var, head, headname, field) \ + for ((var) = ((var) ? (var) : TAILQ_LAST((head), headname)); \ + (var); \ + (var) = TAILQ_PREV((var), headname, field)) + +#define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \ + for ((var) = TAILQ_LAST((head), headname); \ + (var) && ((tvar) = TAILQ_PREV((var), headname, field), 1); \ + (var) = (tvar)) + +#define TAILQ_FOREACH_REVERSE_FROM_SAFE(var, head, headname, field, tvar) \ + for ((var) = ((var) ? (var) : TAILQ_LAST((head), headname)); \ + (var) && ((tvar) = TAILQ_PREV((var), headname, field), 1); \ + (var) = (tvar)) + +#define TAILQ_INIT(head) do { \ + TAILQ_FIRST((head)) = NULL; \ + (head)->tqh_last = &TAILQ_FIRST((head)); \ + QMD_TRACE_HEAD(head); \ +} while (0) + +#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \ + QMD_TAILQ_CHECK_NEXT(listelm, field); \ + if ((TAILQ_NEXT((elm), field) = TAILQ_NEXT((listelm), field)) != NULL)\ + TAILQ_NEXT((elm), field)->field.tqe_prev = \ + &TAILQ_NEXT((elm), field); \ + else { \ + (head)->tqh_last = &TAILQ_NEXT((elm), field); \ + QMD_TRACE_HEAD(head); \ + } \ + TAILQ_NEXT((listelm), field) = (elm); \ + (elm)->field.tqe_prev = &TAILQ_NEXT((listelm), field); \ + QMD_TRACE_ELEM(&(elm)->field); \ + QMD_TRACE_ELEM(&(listelm)->field); \ +} while (0) + +#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \ + QMD_TAILQ_CHECK_PREV(listelm, field); \ + (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \ + TAILQ_NEXT((elm), field) = (listelm); \ + *(listelm)->field.tqe_prev = (elm); \ + (listelm)->field.tqe_prev = &TAILQ_NEXT((elm), field); \ + QMD_TRACE_ELEM(&(elm)->field); \ + QMD_TRACE_ELEM(&(listelm)->field); \ +} while (0) + +#define TAILQ_INSERT_HEAD(head, elm, field) do { \ + QMD_TAILQ_CHECK_HEAD(head, field); \ + if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL) \ + TAILQ_FIRST((head))->field.tqe_prev = \ + &TAILQ_NEXT((elm), field); \ + else \ + (head)->tqh_last = &TAILQ_NEXT((elm), field); \ + TAILQ_FIRST((head)) = (elm); \ + (elm)->field.tqe_prev = &TAILQ_FIRST((head)); \ + QMD_TRACE_HEAD(head); \ + QMD_TRACE_ELEM(&(elm)->field); \ +} while (0) + +#define TAILQ_INSERT_TAIL(head, elm, field) do { \ + QMD_TAILQ_CHECK_TAIL(head, field); \ + TAILQ_NEXT((elm), field) = NULL; \ + (elm)->field.tqe_prev = (head)->tqh_last; \ + *(head)->tqh_last = (elm); \ + (head)->tqh_last = &TAILQ_NEXT((elm), field); \ + QMD_TRACE_HEAD(head); \ + QMD_TRACE_ELEM(&(elm)->field); \ +} while (0) + +#define TAILQ_LAST(head, headname) \ + (*(((struct headname *)((head)->tqh_last))->tqh_last)) + +/* + * The FAST function is fast in that it causes no data access other + * then the access to the head. The standard LAST function above + * will cause a data access of both the element you want and + * the previous element. FAST is very useful for instances when + * you may want to prefetch the last data element. + */ +#define TAILQ_LAST_FAST(head, type, field) \ + (TAILQ_EMPTY(head) ? NULL : __containerof((head)->tqh_last, QUEUE_TYPEOF(type), field.tqe_next)) + +#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) + +#define TAILQ_PREV(elm, headname, field) \ + (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last)) + +#define TAILQ_REMOVE(head, elm, field) do { \ + QMD_SAVELINK(oldnext, (elm)->field.tqe_next); \ + QMD_SAVELINK(oldprev, (elm)->field.tqe_prev); \ + QMD_TAILQ_CHECK_NEXT(elm, field); \ + QMD_TAILQ_CHECK_PREV(elm, field); \ + if ((TAILQ_NEXT((elm), field)) != NULL) \ + TAILQ_NEXT((elm), field)->field.tqe_prev = \ + (elm)->field.tqe_prev; \ + else { \ + (head)->tqh_last = (elm)->field.tqe_prev; \ + QMD_TRACE_HEAD(head); \ + } \ + *(elm)->field.tqe_prev = TAILQ_NEXT((elm), field); \ + TRASHIT(*oldnext); \ + TRASHIT(*oldprev); \ + QMD_TRACE_ELEM(&(elm)->field); \ +} while (0) + +#define TAILQ_SWAP(head1, head2, type, field) do { \ + QUEUE_TYPEOF(type) *swap_first = (head1)->tqh_first; \ + QUEUE_TYPEOF(type) **swap_last = (head1)->tqh_last; \ + (head1)->tqh_first = (head2)->tqh_first; \ + (head1)->tqh_last = (head2)->tqh_last; \ + (head2)->tqh_first = swap_first; \ + (head2)->tqh_last = swap_last; \ + if ((swap_first = (head1)->tqh_first) != NULL) \ + swap_first->field.tqe_prev = &(head1)->tqh_first; \ + else \ + (head1)->tqh_last = &(head1)->tqh_first; \ + if ((swap_first = (head2)->tqh_first) != NULL) \ + swap_first->field.tqe_prev = &(head2)->tqh_first; \ + else \ + (head2)->tqh_last = &(head2)->tqh_first; \ +} while (0) + +#endif /* !_SYS_QUEUE_H_ */ diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index e90264f8b..818f4e9cb 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -32,16 +32,13 @@ INCLUDING NEGLIGENCE OR OTHERWISE ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - This file is part of the tinyusb stack. -*/ + This file is part of the tinyusb stack. + */ /**************************************************************************/ #include "tusb_fifo.h" #include "common/tusb_verify.h" // for ASSERT -/*------------------------------------------------------------------*/ -/* - *------------------------------------------------------------------*/ #if CFG_FIFO_MUTEX #define mutex_lock_if_needed(_ff) if (_ff->mutex) tu_fifo_mutex_lock(_ff->mutex) @@ -54,17 +51,6 @@ #endif -static inline uint16_t tu_min16(uint16_t x, uint16_t y) -{ - return (x < y) ? x : y; -} - -static inline bool tu_fifo_initalized(tu_fifo_t* f) -{ - return (f->buffer != NULL) && (f->depth > 0) && (f->item_size > 0); -} - - void tu_fifo_config(tu_fifo_t *f, void* buffer, uint16_t depth, uint16_t item_size, bool overwritable) { mutex_lock_if_needed(f); @@ -98,7 +84,6 @@ void tu_fifo_config(tu_fifo_t *f, void* buffer, uint16_t depth, uint16_t item_si /******************************************************************************/ bool tu_fifo_read(tu_fifo_t* f, void * p_buffer) { - if( !tu_fifo_initalized(f) ) return false; if( tu_fifo_empty(f) ) return false; mutex_lock_if_needed(f); @@ -132,12 +117,10 @@ bool tu_fifo_read(tu_fifo_t* f, void * p_buffer) /******************************************************************************/ uint16_t tu_fifo_read_n (tu_fifo_t* f, void * p_buffer, uint16_t count) { - if( !tu_fifo_initalized(f) ) return 0; if( tu_fifo_empty(f) ) return 0; /* Limit up to fifo's count */ - count = tu_min16(count, f->count); - if( count == 0 ) return 0; + if ( count > f->count ) count = f->count; mutex_lock_if_needed(f); @@ -176,7 +159,6 @@ uint16_t tu_fifo_read_n (tu_fifo_t* f, void * p_buffer, uint16_t count) /******************************************************************************/ bool tu_fifo_peek_at(tu_fifo_t* f, uint16_t pos, void * p_buffer) { - if ( !tu_fifo_initalized(f) ) return false; if ( pos >= f->count ) return false; // rd_idx is pos=0 @@ -205,10 +187,8 @@ bool tu_fifo_peek_at(tu_fifo_t* f, uint16_t pos, void * p_buffer) FIFO will always return TRUE) */ /******************************************************************************/ -bool tu_fifo_write(tu_fifo_t* f, void const * p_data) +bool tu_fifo_write (tu_fifo_t* f, const void * p_data) { - if ( !tu_fifo_initalized(f) ) return false; - // if ( tu_fifo_full(f) && !f->overwritable ) return false; TU_ASSERT( !(tu_fifo_full(f) && !f->overwritable) ); @@ -249,7 +229,7 @@ bool tu_fifo_write(tu_fifo_t* f, void const * p_data) @return Number of written elements */ /******************************************************************************/ -uint16_t tu_fifo_write_n(tu_fifo_t* f, void const * p_data, uint16_t count) +uint16_t tu_fifo_write_n (tu_fifo_t* f, const void * p_data, uint16_t count) { if ( count == 0 ) return 0; -- cgit v1.3.1 From a6870add9521365727050387bdebff7c1c959f63 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 26 Sep 2018 01:44:36 +0700 Subject: format queue.h a bit --- src/common/queue.h | 60 +++++++++++++++++++++++++++--------------------------- 1 file changed, 30 insertions(+), 30 deletions(-) (limited to 'src/common') diff --git a/src/common/queue.h b/src/common/queue.h index 767f43fed..443f01b22 100644 --- a/src/common/queue.h +++ b/src/common/queue.h @@ -83,36 +83,36 @@ * - means the macro is not available * s means the macro is available but is slow (runs in O(n) time) * - * SLIST LIST STAILQ TAILQ - * _HEAD + + + + - * _CLASS_HEAD + + + + - * _HEAD_INITIALIZER + + + + - * _ENTRY + + + + - * _CLASS_ENTRY + + + + - * _INIT + + + + - * _EMPTY + + + + - * _FIRST + + + + - * _NEXT + + + + - * _PREV - + - + - * _LAST - - + + - * _LAST_FAST - - - + - * _FOREACH + + + + - * _FOREACH_FROM + + + + - * _FOREACH_SAFE + + + + - * _FOREACH_FROM_SAFE + + + + - * _FOREACH_REVERSE - - - + - * _FOREACH_REVERSE_FROM - - - + - * _FOREACH_REVERSE_SAFE - - - + - * _FOREACH_REVERSE_FROM_SAFE - - - + - * _INSERT_HEAD + + + + - * _INSERT_BEFORE - + - + - * _INSERT_AFTER + + + + - * _INSERT_TAIL - - + + - * _CONCAT s s + + - * _REMOVE_AFTER + - + - - * _REMOVE_HEAD + - + - - * _REMOVE s + s + - * _SWAP + + + + + * SLIST LIST STAILQ TAILQ + * _HEAD + + + + + * _CLASS_HEAD + + + + + * _HEAD_INITIALIZER + + + + + * _ENTRY + + + + + * _CLASS_ENTRY + + + + + * _INIT + + + + + * _EMPTY + + + + + * _FIRST + + + + + * _NEXT + + + + + * _PREV - + - + + * _LAST - - + + + * _LAST_FAST - - - + + * _FOREACH + + + + + * _FOREACH_FROM + + + + + * _FOREACH_SAFE + + + + + * _FOREACH_FROM_SAFE + + + + + * _FOREACH_REVERSE - - - + + * _FOREACH_REVERSE_FROM - - - + + * _FOREACH_REVERSE_SAFE - - - + + * _FOREACH_REVERSE_FROM_SAFE - - - + + * _INSERT_HEAD + + + + + * _INSERT_BEFORE - + - + + * _INSERT_AFTER + + + + + * _INSERT_TAIL - - + + + * _CONCAT s s + + + * _REMOVE_AFTER + - + - + * _REMOVE_HEAD + - + - + * _REMOVE s + s + + * _SWAP + + + + * */ #ifdef QUEUE_MACRO_DEBUG -- cgit v1.3.1 From 99c5219dc17cfc58f7070b6257fda82732da5768 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 28 Sep 2018 01:59:47 +0700 Subject: rename queue.h to sys_queue.h to prevent name conflict --- src/common/queue.h | 871 ------------------------------------------------- src/common/sys_queue.h | 871 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 871 insertions(+), 871 deletions(-) delete mode 100644 src/common/queue.h create mode 100644 src/common/sys_queue.h (limited to 'src/common') diff --git a/src/common/queue.h b/src/common/queue.h deleted file mode 100644 index 443f01b22..000000000 --- a/src/common/queue.h +++ /dev/null @@ -1,871 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-3-Clause - * - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)queue.h 8.5 (Berkeley) 8/20/94 - * $FreeBSD$ - */ - -#ifndef _SYS_QUEUE_H_ -#define _SYS_QUEUE_H_ - -#include - -/* - * This file defines four types of data structures: singly-linked lists, - * singly-linked tail queues, lists and tail queues. - * - * A singly-linked list is headed by a single forward pointer. The elements - * are singly linked for minimum space and pointer manipulation overhead at - * the expense of O(n) removal for arbitrary elements. New elements can be - * added to the list after an existing element or at the head of the list. - * Elements being removed from the head of the list should use the explicit - * macro for this purpose for optimum efficiency. A singly-linked list may - * only be traversed in the forward direction. Singly-linked lists are ideal - * for applications with large datasets and few or no removals or for - * implementing a LIFO queue. - * - * A singly-linked tail queue is headed by a pair of pointers, one to the - * head of the list and the other to the tail of the list. The elements are - * singly linked for minimum space and pointer manipulation overhead at the - * expense of O(n) removal for arbitrary elements. New elements can be added - * to the list after an existing element, at the head of the list, or at the - * end of the list. Elements being removed from the head of the tail queue - * should use the explicit macro for this purpose for optimum efficiency. - * A singly-linked tail queue may only be traversed in the forward direction. - * Singly-linked tail queues are ideal for applications with large datasets - * and few or no removals or for implementing a FIFO queue. - * - * A list is headed by a single forward pointer (or an array of forward - * pointers for a hash table header). The elements are doubly linked - * so that an arbitrary element can be removed without a need to - * traverse the list. New elements can be added to the list before - * or after an existing element or at the head of the list. A list - * may be traversed in either direction. - * - * A tail queue is headed by a pair of pointers, one to the head of the - * list and the other to the tail of the list. The elements are doubly - * linked so that an arbitrary element can be removed without a need to - * traverse the list. New elements can be added to the list before or - * after an existing element, at the head of the list, or at the end of - * the list. A tail queue may be traversed in either direction. - * - * For details on the use of these macros, see the queue(3) manual page. - * - * Below is a summary of implemented functions where: - * + means the macro is available - * - means the macro is not available - * s means the macro is available but is slow (runs in O(n) time) - * - * SLIST LIST STAILQ TAILQ - * _HEAD + + + + - * _CLASS_HEAD + + + + - * _HEAD_INITIALIZER + + + + - * _ENTRY + + + + - * _CLASS_ENTRY + + + + - * _INIT + + + + - * _EMPTY + + + + - * _FIRST + + + + - * _NEXT + + + + - * _PREV - + - + - * _LAST - - + + - * _LAST_FAST - - - + - * _FOREACH + + + + - * _FOREACH_FROM + + + + - * _FOREACH_SAFE + + + + - * _FOREACH_FROM_SAFE + + + + - * _FOREACH_REVERSE - - - + - * _FOREACH_REVERSE_FROM - - - + - * _FOREACH_REVERSE_SAFE - - - + - * _FOREACH_REVERSE_FROM_SAFE - - - + - * _INSERT_HEAD + + + + - * _INSERT_BEFORE - + - + - * _INSERT_AFTER + + + + - * _INSERT_TAIL - - + + - * _CONCAT s s + + - * _REMOVE_AFTER + - + - - * _REMOVE_HEAD + - + - - * _REMOVE s + s + - * _SWAP + + + + - * - */ -#ifdef QUEUE_MACRO_DEBUG -#warn Use QUEUE_MACRO_DEBUG_TRACE and/or QUEUE_MACRO_DEBUG_TRASH -#define QUEUE_MACRO_DEBUG_TRACE -#define QUEUE_MACRO_DEBUG_TRASH -#endif - -#ifdef QUEUE_MACRO_DEBUG_TRACE -/* Store the last 2 places the queue element or head was altered */ -struct qm_trace { - unsigned long lastline; - unsigned long prevline; - const char *lastfile; - const char *prevfile; -}; - -#define TRACEBUF struct qm_trace trace; -#define TRACEBUF_INITIALIZER { __LINE__, 0, __FILE__, NULL } , - -#define QMD_TRACE_HEAD(head) do { \ - (head)->trace.prevline = (head)->trace.lastline; \ - (head)->trace.prevfile = (head)->trace.lastfile; \ - (head)->trace.lastline = __LINE__; \ - (head)->trace.lastfile = __FILE__; \ -} while (0) - -#define QMD_TRACE_ELEM(elem) do { \ - (elem)->trace.prevline = (elem)->trace.lastline; \ - (elem)->trace.prevfile = (elem)->trace.lastfile; \ - (elem)->trace.lastline = __LINE__; \ - (elem)->trace.lastfile = __FILE__; \ -} while (0) - -#else /* !QUEUE_MACRO_DEBUG_TRACE */ -#define QMD_TRACE_ELEM(elem) -#define QMD_TRACE_HEAD(head) -#define TRACEBUF -#define TRACEBUF_INITIALIZER -#endif /* QUEUE_MACRO_DEBUG_TRACE */ - -#ifdef QUEUE_MACRO_DEBUG_TRASH -#define TRASHIT(x) do {(x) = (void *)-1;} while (0) -#define QMD_IS_TRASHED(x) ((x) == (void *)(intptr_t)-1) -#else /* !QUEUE_MACRO_DEBUG_TRASH */ -#define TRASHIT(x) -#define QMD_IS_TRASHED(x) 0 -#endif /* QUEUE_MACRO_DEBUG_TRASH */ - -#if defined(QUEUE_MACRO_DEBUG_TRACE) || defined(QUEUE_MACRO_DEBUG_TRASH) -#define QMD_SAVELINK(name, link) void **name = (void *)&(link) -#else /* !QUEUE_MACRO_DEBUG_TRACE && !QUEUE_MACRO_DEBUG_TRASH */ -#define QMD_SAVELINK(name, link) -#endif /* QUEUE_MACRO_DEBUG_TRACE || QUEUE_MACRO_DEBUG_TRASH */ - -#ifdef __cplusplus -/* - * In C++ there can be structure lists and class lists: - */ -#define QUEUE_TYPEOF(type) type -#else -#define QUEUE_TYPEOF(type) struct type -#endif - -/* - * Singly-linked List declarations. - */ -#define SLIST_HEAD(name, type) \ -struct name { \ - struct type *slh_first; /* first element */ \ -} - -#define SLIST_CLASS_HEAD(name, type) \ -struct name { \ - class type *slh_first; /* first element */ \ -} - -#define SLIST_HEAD_INITIALIZER(head) \ - { NULL } - -#define SLIST_ENTRY(type) \ -struct { \ - struct type *sle_next; /* next element */ \ -} - -#define SLIST_CLASS_ENTRY(type) \ -struct { \ - class type *sle_next; /* next element */ \ -} - -/* - * Singly-linked List functions. - */ -#if (defined(_KERNEL) && defined(INVARIANTS)) -#define QMD_SLIST_CHECK_PREVPTR(prevp, elm) do { \ - if (*(prevp) != (elm)) \ - panic("Bad prevptr *(%p) == %p != %p", \ - (prevp), *(prevp), (elm)); \ -} while (0) -#else -#define QMD_SLIST_CHECK_PREVPTR(prevp, elm) -#endif - -#define SLIST_CONCAT(head1, head2, type, field) do { \ - QUEUE_TYPEOF(type) *curelm = SLIST_FIRST(head1); \ - if (curelm == NULL) { \ - if ((SLIST_FIRST(head1) = SLIST_FIRST(head2)) != NULL) \ - SLIST_INIT(head2); \ - } else if (SLIST_FIRST(head2) != NULL) { \ - while (SLIST_NEXT(curelm, field) != NULL) \ - curelm = SLIST_NEXT(curelm, field); \ - SLIST_NEXT(curelm, field) = SLIST_FIRST(head2); \ - SLIST_INIT(head2); \ - } \ -} while (0) - -#define SLIST_EMPTY(head) ((head)->slh_first == NULL) - -#define SLIST_FIRST(head) ((head)->slh_first) - -#define SLIST_FOREACH(var, head, field) \ - for ((var) = SLIST_FIRST((head)); \ - (var); \ - (var) = SLIST_NEXT((var), field)) - -#define SLIST_FOREACH_FROM(var, head, field) \ - for ((var) = ((var) ? (var) : SLIST_FIRST((head))); \ - (var); \ - (var) = SLIST_NEXT((var), field)) - -#define SLIST_FOREACH_SAFE(var, head, field, tvar) \ - for ((var) = SLIST_FIRST((head)); \ - (var) && ((tvar) = SLIST_NEXT((var), field), 1); \ - (var) = (tvar)) - -#define SLIST_FOREACH_FROM_SAFE(var, head, field, tvar) \ - for ((var) = ((var) ? (var) : SLIST_FIRST((head))); \ - (var) && ((tvar) = SLIST_NEXT((var), field), 1); \ - (var) = (tvar)) - -#define SLIST_FOREACH_PREVPTR(var, varp, head, field) \ - for ((varp) = &SLIST_FIRST((head)); \ - ((var) = *(varp)) != NULL; \ - (varp) = &SLIST_NEXT((var), field)) - -#define SLIST_INIT(head) do { \ - SLIST_FIRST((head)) = NULL; \ -} while (0) - -#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \ - SLIST_NEXT((elm), field) = SLIST_NEXT((slistelm), field); \ - SLIST_NEXT((slistelm), field) = (elm); \ -} while (0) - -#define SLIST_INSERT_HEAD(head, elm, field) do { \ - SLIST_NEXT((elm), field) = SLIST_FIRST((head)); \ - SLIST_FIRST((head)) = (elm); \ -} while (0) - -#define SLIST_NEXT(elm, field) ((elm)->field.sle_next) - -#define SLIST_REMOVE(head, elm, type, field) do { \ - QMD_SAVELINK(oldnext, (elm)->field.sle_next); \ - if (SLIST_FIRST((head)) == (elm)) { \ - SLIST_REMOVE_HEAD((head), field); \ - } \ - else { \ - QUEUE_TYPEOF(type) *curelm = SLIST_FIRST(head); \ - while (SLIST_NEXT(curelm, field) != (elm)) \ - curelm = SLIST_NEXT(curelm, field); \ - SLIST_REMOVE_AFTER(curelm, field); \ - } \ - TRASHIT(*oldnext); \ -} while (0) - -#define SLIST_REMOVE_AFTER(elm, field) do { \ - SLIST_NEXT(elm, field) = \ - SLIST_NEXT(SLIST_NEXT(elm, field), field); \ -} while (0) - -#define SLIST_REMOVE_HEAD(head, field) do { \ - SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field); \ -} while (0) - -#define SLIST_REMOVE_PREVPTR(prevp, elm, field) do { \ - QMD_SLIST_CHECK_PREVPTR(prevp, elm); \ - *(prevp) = SLIST_NEXT(elm, field); \ - TRASHIT((elm)->field.sle_next); \ -} while (0) - -#define SLIST_SWAP(head1, head2, type) do { \ - QUEUE_TYPEOF(type) *swap_first = SLIST_FIRST(head1); \ - SLIST_FIRST(head1) = SLIST_FIRST(head2); \ - SLIST_FIRST(head2) = swap_first; \ -} while (0) - -/* - * Singly-linked Tail queue declarations. - */ -#define STAILQ_HEAD(name, type) \ -struct name { \ - struct type *stqh_first;/* first element */ \ - struct type **stqh_last;/* addr of last next element */ \ -} - -#define STAILQ_CLASS_HEAD(name, type) \ -struct name { \ - class type *stqh_first; /* first element */ \ - class type **stqh_last; /* addr of last next element */ \ -} - -#define STAILQ_HEAD_INITIALIZER(head) \ - { NULL, &(head).stqh_first } - -#define STAILQ_ENTRY(type) \ -struct { \ - struct type *stqe_next; /* next element */ \ -} - -#define STAILQ_CLASS_ENTRY(type) \ -struct { \ - class type *stqe_next; /* next element */ \ -} - -/* - * Singly-linked Tail queue functions. - */ -#define STAILQ_CONCAT(head1, head2) do { \ - if (!STAILQ_EMPTY((head2))) { \ - *(head1)->stqh_last = (head2)->stqh_first; \ - (head1)->stqh_last = (head2)->stqh_last; \ - STAILQ_INIT((head2)); \ - } \ -} while (0) - -#define STAILQ_EMPTY(head) ((head)->stqh_first == NULL) - -#define STAILQ_FIRST(head) ((head)->stqh_first) - -#define STAILQ_FOREACH(var, head, field) \ - for((var) = STAILQ_FIRST((head)); \ - (var); \ - (var) = STAILQ_NEXT((var), field)) - -#define STAILQ_FOREACH_FROM(var, head, field) \ - for ((var) = ((var) ? (var) : STAILQ_FIRST((head))); \ - (var); \ - (var) = STAILQ_NEXT((var), field)) - -#define STAILQ_FOREACH_SAFE(var, head, field, tvar) \ - for ((var) = STAILQ_FIRST((head)); \ - (var) && ((tvar) = STAILQ_NEXT((var), field), 1); \ - (var) = (tvar)) - -#define STAILQ_FOREACH_FROM_SAFE(var, head, field, tvar) \ - for ((var) = ((var) ? (var) : STAILQ_FIRST((head))); \ - (var) && ((tvar) = STAILQ_NEXT((var), field), 1); \ - (var) = (tvar)) - -#define STAILQ_INIT(head) do { \ - STAILQ_FIRST((head)) = NULL; \ - (head)->stqh_last = &STAILQ_FIRST((head)); \ -} while (0) - -#define STAILQ_INSERT_AFTER(head, tqelm, elm, field) do { \ - if ((STAILQ_NEXT((elm), field) = STAILQ_NEXT((tqelm), field)) == NULL)\ - (head)->stqh_last = &STAILQ_NEXT((elm), field); \ - STAILQ_NEXT((tqelm), field) = (elm); \ -} while (0) - -#define STAILQ_INSERT_HEAD(head, elm, field) do { \ - if ((STAILQ_NEXT((elm), field) = STAILQ_FIRST((head))) == NULL) \ - (head)->stqh_last = &STAILQ_NEXT((elm), field); \ - STAILQ_FIRST((head)) = (elm); \ -} while (0) - -#define STAILQ_INSERT_TAIL(head, elm, field) do { \ - STAILQ_NEXT((elm), field) = NULL; \ - *(head)->stqh_last = (elm); \ - (head)->stqh_last = &STAILQ_NEXT((elm), field); \ -} while (0) - -#define STAILQ_LAST(head, type, field) \ - (STAILQ_EMPTY((head)) ? NULL : \ - __containerof((head)->stqh_last, \ - QUEUE_TYPEOF(type), field.stqe_next)) - -#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next) - -#define STAILQ_REMOVE(head, elm, type, field) do { \ - QMD_SAVELINK(oldnext, (elm)->field.stqe_next); \ - if (STAILQ_FIRST((head)) == (elm)) { \ - STAILQ_REMOVE_HEAD((head), field); \ - } \ - else { \ - QUEUE_TYPEOF(type) *curelm = STAILQ_FIRST(head); \ - while (STAILQ_NEXT(curelm, field) != (elm)) \ - curelm = STAILQ_NEXT(curelm, field); \ - STAILQ_REMOVE_AFTER(head, curelm, field); \ - } \ - TRASHIT(*oldnext); \ -} while (0) - -#define STAILQ_REMOVE_AFTER(head, elm, field) do { \ - if ((STAILQ_NEXT(elm, field) = \ - STAILQ_NEXT(STAILQ_NEXT(elm, field), field)) == NULL) \ - (head)->stqh_last = &STAILQ_NEXT((elm), field); \ -} while (0) - -#define STAILQ_REMOVE_HEAD(head, field) do { \ - if ((STAILQ_FIRST((head)) = \ - STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL) \ - (head)->stqh_last = &STAILQ_FIRST((head)); \ -} while (0) - -#define STAILQ_SWAP(head1, head2, type) do { \ - QUEUE_TYPEOF(type) *swap_first = STAILQ_FIRST(head1); \ - QUEUE_TYPEOF(type) **swap_last = (head1)->stqh_last; \ - STAILQ_FIRST(head1) = STAILQ_FIRST(head2); \ - (head1)->stqh_last = (head2)->stqh_last; \ - STAILQ_FIRST(head2) = swap_first; \ - (head2)->stqh_last = swap_last; \ - if (STAILQ_EMPTY(head1)) \ - (head1)->stqh_last = &STAILQ_FIRST(head1); \ - if (STAILQ_EMPTY(head2)) \ - (head2)->stqh_last = &STAILQ_FIRST(head2); \ -} while (0) - - -/* - * List declarations. - */ -#define LIST_HEAD(name, type) \ -struct name { \ - struct type *lh_first; /* first element */ \ -} - -#define LIST_CLASS_HEAD(name, type) \ -struct name { \ - class type *lh_first; /* first element */ \ -} - -#define LIST_HEAD_INITIALIZER(head) \ - { NULL } - -#define LIST_ENTRY(type) \ -struct { \ - struct type *le_next; /* next element */ \ - struct type **le_prev; /* address of previous next element */ \ -} - -#define LIST_CLASS_ENTRY(type) \ -struct { \ - class type *le_next; /* next element */ \ - class type **le_prev; /* address of previous next element */ \ -} - -/* - * List functions. - */ - -#if (defined(_KERNEL) && defined(INVARIANTS)) -/* - * QMD_LIST_CHECK_HEAD(LIST_HEAD *head, LIST_ENTRY NAME) - * - * If the list is non-empty, validates that the first element of the list - * points back at 'head.' - */ -#define QMD_LIST_CHECK_HEAD(head, field) do { \ - if (LIST_FIRST((head)) != NULL && \ - LIST_FIRST((head))->field.le_prev != \ - &LIST_FIRST((head))) \ - panic("Bad list head %p first->prev != head", (head)); \ -} while (0) - -/* - * QMD_LIST_CHECK_NEXT(TYPE *elm, LIST_ENTRY NAME) - * - * If an element follows 'elm' in the list, validates that the next element - * points back at 'elm.' - */ -#define QMD_LIST_CHECK_NEXT(elm, field) do { \ - if (LIST_NEXT((elm), field) != NULL && \ - LIST_NEXT((elm), field)->field.le_prev != \ - &((elm)->field.le_next)) \ - panic("Bad link elm %p next->prev != elm", (elm)); \ -} while (0) - -/* - * QMD_LIST_CHECK_PREV(TYPE *elm, LIST_ENTRY NAME) - * - * Validates that the previous element (or head of the list) points to 'elm.' - */ -#define QMD_LIST_CHECK_PREV(elm, field) do { \ - if (*(elm)->field.le_prev != (elm)) \ - panic("Bad link elm %p prev->next != elm", (elm)); \ -} while (0) -#else -#define QMD_LIST_CHECK_HEAD(head, field) -#define QMD_LIST_CHECK_NEXT(elm, field) -#define QMD_LIST_CHECK_PREV(elm, field) -#endif /* (_KERNEL && INVARIANTS) */ - -#define LIST_CONCAT(head1, head2, type, field) do { \ - QUEUE_TYPEOF(type) *curelm = LIST_FIRST(head1); \ - if (curelm == NULL) { \ - if ((LIST_FIRST(head1) = LIST_FIRST(head2)) != NULL) { \ - LIST_FIRST(head2)->field.le_prev = \ - &LIST_FIRST((head1)); \ - LIST_INIT(head2); \ - } \ - } else if (LIST_FIRST(head2) != NULL) { \ - while (LIST_NEXT(curelm, field) != NULL) \ - curelm = LIST_NEXT(curelm, field); \ - LIST_NEXT(curelm, field) = LIST_FIRST(head2); \ - LIST_FIRST(head2)->field.le_prev = &LIST_NEXT(curelm, field); \ - LIST_INIT(head2); \ - } \ -} while (0) - -#define LIST_EMPTY(head) ((head)->lh_first == NULL) - -#define LIST_FIRST(head) ((head)->lh_first) - -#define LIST_FOREACH(var, head, field) \ - for ((var) = LIST_FIRST((head)); \ - (var); \ - (var) = LIST_NEXT((var), field)) - -#define LIST_FOREACH_FROM(var, head, field) \ - for ((var) = ((var) ? (var) : LIST_FIRST((head))); \ - (var); \ - (var) = LIST_NEXT((var), field)) - -#define LIST_FOREACH_SAFE(var, head, field, tvar) \ - for ((var) = LIST_FIRST((head)); \ - (var) && ((tvar) = LIST_NEXT((var), field), 1); \ - (var) = (tvar)) - -#define LIST_FOREACH_FROM_SAFE(var, head, field, tvar) \ - for ((var) = ((var) ? (var) : LIST_FIRST((head))); \ - (var) && ((tvar) = LIST_NEXT((var), field), 1); \ - (var) = (tvar)) - -#define LIST_INIT(head) do { \ - LIST_FIRST((head)) = NULL; \ -} while (0) - -#define LIST_INSERT_AFTER(listelm, elm, field) do { \ - QMD_LIST_CHECK_NEXT(listelm, field); \ - if ((LIST_NEXT((elm), field) = LIST_NEXT((listelm), field)) != NULL)\ - LIST_NEXT((listelm), field)->field.le_prev = \ - &LIST_NEXT((elm), field); \ - LIST_NEXT((listelm), field) = (elm); \ - (elm)->field.le_prev = &LIST_NEXT((listelm), field); \ -} while (0) - -#define LIST_INSERT_BEFORE(listelm, elm, field) do { \ - QMD_LIST_CHECK_PREV(listelm, field); \ - (elm)->field.le_prev = (listelm)->field.le_prev; \ - LIST_NEXT((elm), field) = (listelm); \ - *(listelm)->field.le_prev = (elm); \ - (listelm)->field.le_prev = &LIST_NEXT((elm), field); \ -} while (0) - -#define LIST_INSERT_HEAD(head, elm, field) do { \ - QMD_LIST_CHECK_HEAD((head), field); \ - if ((LIST_NEXT((elm), field) = LIST_FIRST((head))) != NULL) \ - LIST_FIRST((head))->field.le_prev = &LIST_NEXT((elm), field);\ - LIST_FIRST((head)) = (elm); \ - (elm)->field.le_prev = &LIST_FIRST((head)); \ -} while (0) - -#define LIST_NEXT(elm, field) ((elm)->field.le_next) - -#define LIST_PREV(elm, head, type, field) \ - ((elm)->field.le_prev == &LIST_FIRST((head)) ? NULL : \ - __containerof((elm)->field.le_prev, \ - QUEUE_TYPEOF(type), field.le_next)) - -#define LIST_REMOVE(elm, field) do { \ - QMD_SAVELINK(oldnext, (elm)->field.le_next); \ - QMD_SAVELINK(oldprev, (elm)->field.le_prev); \ - QMD_LIST_CHECK_NEXT(elm, field); \ - QMD_LIST_CHECK_PREV(elm, field); \ - if (LIST_NEXT((elm), field) != NULL) \ - LIST_NEXT((elm), field)->field.le_prev = \ - (elm)->field.le_prev; \ - *(elm)->field.le_prev = LIST_NEXT((elm), field); \ - TRASHIT(*oldnext); \ - TRASHIT(*oldprev); \ -} while (0) - -#define LIST_SWAP(head1, head2, type, field) do { \ - QUEUE_TYPEOF(type) *swap_tmp = LIST_FIRST(head1); \ - LIST_FIRST((head1)) = LIST_FIRST((head2)); \ - LIST_FIRST((head2)) = swap_tmp; \ - if ((swap_tmp = LIST_FIRST((head1))) != NULL) \ - swap_tmp->field.le_prev = &LIST_FIRST((head1)); \ - if ((swap_tmp = LIST_FIRST((head2))) != NULL) \ - swap_tmp->field.le_prev = &LIST_FIRST((head2)); \ -} while (0) - -/* - * Tail queue declarations. - */ -#define TAILQ_HEAD(name, type) \ -struct name { \ - struct type *tqh_first; /* first element */ \ - struct type **tqh_last; /* addr of last next element */ \ - TRACEBUF \ -} - -#define TAILQ_CLASS_HEAD(name, type) \ -struct name { \ - class type *tqh_first; /* first element */ \ - class type **tqh_last; /* addr of last next element */ \ - TRACEBUF \ -} - -#define TAILQ_HEAD_INITIALIZER(head) \ - { NULL, &(head).tqh_first, TRACEBUF_INITIALIZER } - -#define TAILQ_ENTRY(type) \ -struct { \ - struct type *tqe_next; /* next element */ \ - struct type **tqe_prev; /* address of previous next element */ \ - TRACEBUF \ -} - -#define TAILQ_CLASS_ENTRY(type) \ -struct { \ - class type *tqe_next; /* next element */ \ - class type **tqe_prev; /* address of previous next element */ \ - TRACEBUF \ -} - -/* - * Tail queue functions. - */ -#if (defined(_KERNEL) && defined(INVARIANTS)) -/* - * QMD_TAILQ_CHECK_HEAD(TAILQ_HEAD *head, TAILQ_ENTRY NAME) - * - * If the tailq is non-empty, validates that the first element of the tailq - * points back at 'head.' - */ -#define QMD_TAILQ_CHECK_HEAD(head, field) do { \ - if (!TAILQ_EMPTY(head) && \ - TAILQ_FIRST((head))->field.tqe_prev != \ - &TAILQ_FIRST((head))) \ - panic("Bad tailq head %p first->prev != head", (head)); \ -} while (0) - -/* - * QMD_TAILQ_CHECK_TAIL(TAILQ_HEAD *head, TAILQ_ENTRY NAME) - * - * Validates that the tail of the tailq is a pointer to pointer to NULL. - */ -#define QMD_TAILQ_CHECK_TAIL(head, field) do { \ - if (*(head)->tqh_last != NULL) \ - panic("Bad tailq NEXT(%p->tqh_last) != NULL", (head)); \ -} while (0) - -/* - * QMD_TAILQ_CHECK_NEXT(TYPE *elm, TAILQ_ENTRY NAME) - * - * If an element follows 'elm' in the tailq, validates that the next element - * points back at 'elm.' - */ -#define QMD_TAILQ_CHECK_NEXT(elm, field) do { \ - if (TAILQ_NEXT((elm), field) != NULL && \ - TAILQ_NEXT((elm), field)->field.tqe_prev != \ - &((elm)->field.tqe_next)) \ - panic("Bad link elm %p next->prev != elm", (elm)); \ -} while (0) - -/* - * QMD_TAILQ_CHECK_PREV(TYPE *elm, TAILQ_ENTRY NAME) - * - * Validates that the previous element (or head of the tailq) points to 'elm.' - */ -#define QMD_TAILQ_CHECK_PREV(elm, field) do { \ - if (*(elm)->field.tqe_prev != (elm)) \ - panic("Bad link elm %p prev->next != elm", (elm)); \ -} while (0) -#else -#define QMD_TAILQ_CHECK_HEAD(head, field) -#define QMD_TAILQ_CHECK_TAIL(head, headname) -#define QMD_TAILQ_CHECK_NEXT(elm, field) -#define QMD_TAILQ_CHECK_PREV(elm, field) -#endif /* (_KERNEL && INVARIANTS) */ - -#define TAILQ_CONCAT(head1, head2, field) do { \ - if (!TAILQ_EMPTY(head2)) { \ - *(head1)->tqh_last = (head2)->tqh_first; \ - (head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \ - (head1)->tqh_last = (head2)->tqh_last; \ - TAILQ_INIT((head2)); \ - QMD_TRACE_HEAD(head1); \ - QMD_TRACE_HEAD(head2); \ - } \ -} while (0) - -#define TAILQ_EMPTY(head) ((head)->tqh_first == NULL) - -#define TAILQ_FIRST(head) ((head)->tqh_first) - -#define TAILQ_FOREACH(var, head, field) \ - for ((var) = TAILQ_FIRST((head)); \ - (var); \ - (var) = TAILQ_NEXT((var), field)) - -#define TAILQ_FOREACH_FROM(var, head, field) \ - for ((var) = ((var) ? (var) : TAILQ_FIRST((head))); \ - (var); \ - (var) = TAILQ_NEXT((var), field)) - -#define TAILQ_FOREACH_SAFE(var, head, field, tvar) \ - for ((var) = TAILQ_FIRST((head)); \ - (var) && ((tvar) = TAILQ_NEXT((var), field), 1); \ - (var) = (tvar)) - -#define TAILQ_FOREACH_FROM_SAFE(var, head, field, tvar) \ - for ((var) = ((var) ? (var) : TAILQ_FIRST((head))); \ - (var) && ((tvar) = TAILQ_NEXT((var), field), 1); \ - (var) = (tvar)) - -#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \ - for ((var) = TAILQ_LAST((head), headname); \ - (var); \ - (var) = TAILQ_PREV((var), headname, field)) - -#define TAILQ_FOREACH_REVERSE_FROM(var, head, headname, field) \ - for ((var) = ((var) ? (var) : TAILQ_LAST((head), headname)); \ - (var); \ - (var) = TAILQ_PREV((var), headname, field)) - -#define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \ - for ((var) = TAILQ_LAST((head), headname); \ - (var) && ((tvar) = TAILQ_PREV((var), headname, field), 1); \ - (var) = (tvar)) - -#define TAILQ_FOREACH_REVERSE_FROM_SAFE(var, head, headname, field, tvar) \ - for ((var) = ((var) ? (var) : TAILQ_LAST((head), headname)); \ - (var) && ((tvar) = TAILQ_PREV((var), headname, field), 1); \ - (var) = (tvar)) - -#define TAILQ_INIT(head) do { \ - TAILQ_FIRST((head)) = NULL; \ - (head)->tqh_last = &TAILQ_FIRST((head)); \ - QMD_TRACE_HEAD(head); \ -} while (0) - -#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \ - QMD_TAILQ_CHECK_NEXT(listelm, field); \ - if ((TAILQ_NEXT((elm), field) = TAILQ_NEXT((listelm), field)) != NULL)\ - TAILQ_NEXT((elm), field)->field.tqe_prev = \ - &TAILQ_NEXT((elm), field); \ - else { \ - (head)->tqh_last = &TAILQ_NEXT((elm), field); \ - QMD_TRACE_HEAD(head); \ - } \ - TAILQ_NEXT((listelm), field) = (elm); \ - (elm)->field.tqe_prev = &TAILQ_NEXT((listelm), field); \ - QMD_TRACE_ELEM(&(elm)->field); \ - QMD_TRACE_ELEM(&(listelm)->field); \ -} while (0) - -#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \ - QMD_TAILQ_CHECK_PREV(listelm, field); \ - (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \ - TAILQ_NEXT((elm), field) = (listelm); \ - *(listelm)->field.tqe_prev = (elm); \ - (listelm)->field.tqe_prev = &TAILQ_NEXT((elm), field); \ - QMD_TRACE_ELEM(&(elm)->field); \ - QMD_TRACE_ELEM(&(listelm)->field); \ -} while (0) - -#define TAILQ_INSERT_HEAD(head, elm, field) do { \ - QMD_TAILQ_CHECK_HEAD(head, field); \ - if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL) \ - TAILQ_FIRST((head))->field.tqe_prev = \ - &TAILQ_NEXT((elm), field); \ - else \ - (head)->tqh_last = &TAILQ_NEXT((elm), field); \ - TAILQ_FIRST((head)) = (elm); \ - (elm)->field.tqe_prev = &TAILQ_FIRST((head)); \ - QMD_TRACE_HEAD(head); \ - QMD_TRACE_ELEM(&(elm)->field); \ -} while (0) - -#define TAILQ_INSERT_TAIL(head, elm, field) do { \ - QMD_TAILQ_CHECK_TAIL(head, field); \ - TAILQ_NEXT((elm), field) = NULL; \ - (elm)->field.tqe_prev = (head)->tqh_last; \ - *(head)->tqh_last = (elm); \ - (head)->tqh_last = &TAILQ_NEXT((elm), field); \ - QMD_TRACE_HEAD(head); \ - QMD_TRACE_ELEM(&(elm)->field); \ -} while (0) - -#define TAILQ_LAST(head, headname) \ - (*(((struct headname *)((head)->tqh_last))->tqh_last)) - -/* - * The FAST function is fast in that it causes no data access other - * then the access to the head. The standard LAST function above - * will cause a data access of both the element you want and - * the previous element. FAST is very useful for instances when - * you may want to prefetch the last data element. - */ -#define TAILQ_LAST_FAST(head, type, field) \ - (TAILQ_EMPTY(head) ? NULL : __containerof((head)->tqh_last, QUEUE_TYPEOF(type), field.tqe_next)) - -#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) - -#define TAILQ_PREV(elm, headname, field) \ - (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last)) - -#define TAILQ_REMOVE(head, elm, field) do { \ - QMD_SAVELINK(oldnext, (elm)->field.tqe_next); \ - QMD_SAVELINK(oldprev, (elm)->field.tqe_prev); \ - QMD_TAILQ_CHECK_NEXT(elm, field); \ - QMD_TAILQ_CHECK_PREV(elm, field); \ - if ((TAILQ_NEXT((elm), field)) != NULL) \ - TAILQ_NEXT((elm), field)->field.tqe_prev = \ - (elm)->field.tqe_prev; \ - else { \ - (head)->tqh_last = (elm)->field.tqe_prev; \ - QMD_TRACE_HEAD(head); \ - } \ - *(elm)->field.tqe_prev = TAILQ_NEXT((elm), field); \ - TRASHIT(*oldnext); \ - TRASHIT(*oldprev); \ - QMD_TRACE_ELEM(&(elm)->field); \ -} while (0) - -#define TAILQ_SWAP(head1, head2, type, field) do { \ - QUEUE_TYPEOF(type) *swap_first = (head1)->tqh_first; \ - QUEUE_TYPEOF(type) **swap_last = (head1)->tqh_last; \ - (head1)->tqh_first = (head2)->tqh_first; \ - (head1)->tqh_last = (head2)->tqh_last; \ - (head2)->tqh_first = swap_first; \ - (head2)->tqh_last = swap_last; \ - if ((swap_first = (head1)->tqh_first) != NULL) \ - swap_first->field.tqe_prev = &(head1)->tqh_first; \ - else \ - (head1)->tqh_last = &(head1)->tqh_first; \ - if ((swap_first = (head2)->tqh_first) != NULL) \ - swap_first->field.tqe_prev = &(head2)->tqh_first; \ - else \ - (head2)->tqh_last = &(head2)->tqh_first; \ -} while (0) - -#endif /* !_SYS_QUEUE_H_ */ diff --git a/src/common/sys_queue.h b/src/common/sys_queue.h new file mode 100644 index 000000000..443f01b22 --- /dev/null +++ b/src/common/sys_queue.h @@ -0,0 +1,871 @@ +/*- + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)queue.h 8.5 (Berkeley) 8/20/94 + * $FreeBSD$ + */ + +#ifndef _SYS_QUEUE_H_ +#define _SYS_QUEUE_H_ + +#include + +/* + * This file defines four types of data structures: singly-linked lists, + * singly-linked tail queues, lists and tail queues. + * + * A singly-linked list is headed by a single forward pointer. The elements + * are singly linked for minimum space and pointer manipulation overhead at + * the expense of O(n) removal for arbitrary elements. New elements can be + * added to the list after an existing element or at the head of the list. + * Elements being removed from the head of the list should use the explicit + * macro for this purpose for optimum efficiency. A singly-linked list may + * only be traversed in the forward direction. Singly-linked lists are ideal + * for applications with large datasets and few or no removals or for + * implementing a LIFO queue. + * + * A singly-linked tail queue is headed by a pair of pointers, one to the + * head of the list and the other to the tail of the list. The elements are + * singly linked for minimum space and pointer manipulation overhead at the + * expense of O(n) removal for arbitrary elements. New elements can be added + * to the list after an existing element, at the head of the list, or at the + * end of the list. Elements being removed from the head of the tail queue + * should use the explicit macro for this purpose for optimum efficiency. + * A singly-linked tail queue may only be traversed in the forward direction. + * Singly-linked tail queues are ideal for applications with large datasets + * and few or no removals or for implementing a FIFO queue. + * + * A list is headed by a single forward pointer (or an array of forward + * pointers for a hash table header). The elements are doubly linked + * so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list before + * or after an existing element or at the head of the list. A list + * may be traversed in either direction. + * + * A tail queue is headed by a pair of pointers, one to the head of the + * list and the other to the tail of the list. The elements are doubly + * linked so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list before or + * after an existing element, at the head of the list, or at the end of + * the list. A tail queue may be traversed in either direction. + * + * For details on the use of these macros, see the queue(3) manual page. + * + * Below is a summary of implemented functions where: + * + means the macro is available + * - means the macro is not available + * s means the macro is available but is slow (runs in O(n) time) + * + * SLIST LIST STAILQ TAILQ + * _HEAD + + + + + * _CLASS_HEAD + + + + + * _HEAD_INITIALIZER + + + + + * _ENTRY + + + + + * _CLASS_ENTRY + + + + + * _INIT + + + + + * _EMPTY + + + + + * _FIRST + + + + + * _NEXT + + + + + * _PREV - + - + + * _LAST - - + + + * _LAST_FAST - - - + + * _FOREACH + + + + + * _FOREACH_FROM + + + + + * _FOREACH_SAFE + + + + + * _FOREACH_FROM_SAFE + + + + + * _FOREACH_REVERSE - - - + + * _FOREACH_REVERSE_FROM - - - + + * _FOREACH_REVERSE_SAFE - - - + + * _FOREACH_REVERSE_FROM_SAFE - - - + + * _INSERT_HEAD + + + + + * _INSERT_BEFORE - + - + + * _INSERT_AFTER + + + + + * _INSERT_TAIL - - + + + * _CONCAT s s + + + * _REMOVE_AFTER + - + - + * _REMOVE_HEAD + - + - + * _REMOVE s + s + + * _SWAP + + + + + * + */ +#ifdef QUEUE_MACRO_DEBUG +#warn Use QUEUE_MACRO_DEBUG_TRACE and/or QUEUE_MACRO_DEBUG_TRASH +#define QUEUE_MACRO_DEBUG_TRACE +#define QUEUE_MACRO_DEBUG_TRASH +#endif + +#ifdef QUEUE_MACRO_DEBUG_TRACE +/* Store the last 2 places the queue element or head was altered */ +struct qm_trace { + unsigned long lastline; + unsigned long prevline; + const char *lastfile; + const char *prevfile; +}; + +#define TRACEBUF struct qm_trace trace; +#define TRACEBUF_INITIALIZER { __LINE__, 0, __FILE__, NULL } , + +#define QMD_TRACE_HEAD(head) do { \ + (head)->trace.prevline = (head)->trace.lastline; \ + (head)->trace.prevfile = (head)->trace.lastfile; \ + (head)->trace.lastline = __LINE__; \ + (head)->trace.lastfile = __FILE__; \ +} while (0) + +#define QMD_TRACE_ELEM(elem) do { \ + (elem)->trace.prevline = (elem)->trace.lastline; \ + (elem)->trace.prevfile = (elem)->trace.lastfile; \ + (elem)->trace.lastline = __LINE__; \ + (elem)->trace.lastfile = __FILE__; \ +} while (0) + +#else /* !QUEUE_MACRO_DEBUG_TRACE */ +#define QMD_TRACE_ELEM(elem) +#define QMD_TRACE_HEAD(head) +#define TRACEBUF +#define TRACEBUF_INITIALIZER +#endif /* QUEUE_MACRO_DEBUG_TRACE */ + +#ifdef QUEUE_MACRO_DEBUG_TRASH +#define TRASHIT(x) do {(x) = (void *)-1;} while (0) +#define QMD_IS_TRASHED(x) ((x) == (void *)(intptr_t)-1) +#else /* !QUEUE_MACRO_DEBUG_TRASH */ +#define TRASHIT(x) +#define QMD_IS_TRASHED(x) 0 +#endif /* QUEUE_MACRO_DEBUG_TRASH */ + +#if defined(QUEUE_MACRO_DEBUG_TRACE) || defined(QUEUE_MACRO_DEBUG_TRASH) +#define QMD_SAVELINK(name, link) void **name = (void *)&(link) +#else /* !QUEUE_MACRO_DEBUG_TRACE && !QUEUE_MACRO_DEBUG_TRASH */ +#define QMD_SAVELINK(name, link) +#endif /* QUEUE_MACRO_DEBUG_TRACE || QUEUE_MACRO_DEBUG_TRASH */ + +#ifdef __cplusplus +/* + * In C++ there can be structure lists and class lists: + */ +#define QUEUE_TYPEOF(type) type +#else +#define QUEUE_TYPEOF(type) struct type +#endif + +/* + * Singly-linked List declarations. + */ +#define SLIST_HEAD(name, type) \ +struct name { \ + struct type *slh_first; /* first element */ \ +} + +#define SLIST_CLASS_HEAD(name, type) \ +struct name { \ + class type *slh_first; /* first element */ \ +} + +#define SLIST_HEAD_INITIALIZER(head) \ + { NULL } + +#define SLIST_ENTRY(type) \ +struct { \ + struct type *sle_next; /* next element */ \ +} + +#define SLIST_CLASS_ENTRY(type) \ +struct { \ + class type *sle_next; /* next element */ \ +} + +/* + * Singly-linked List functions. + */ +#if (defined(_KERNEL) && defined(INVARIANTS)) +#define QMD_SLIST_CHECK_PREVPTR(prevp, elm) do { \ + if (*(prevp) != (elm)) \ + panic("Bad prevptr *(%p) == %p != %p", \ + (prevp), *(prevp), (elm)); \ +} while (0) +#else +#define QMD_SLIST_CHECK_PREVPTR(prevp, elm) +#endif + +#define SLIST_CONCAT(head1, head2, type, field) do { \ + QUEUE_TYPEOF(type) *curelm = SLIST_FIRST(head1); \ + if (curelm == NULL) { \ + if ((SLIST_FIRST(head1) = SLIST_FIRST(head2)) != NULL) \ + SLIST_INIT(head2); \ + } else if (SLIST_FIRST(head2) != NULL) { \ + while (SLIST_NEXT(curelm, field) != NULL) \ + curelm = SLIST_NEXT(curelm, field); \ + SLIST_NEXT(curelm, field) = SLIST_FIRST(head2); \ + SLIST_INIT(head2); \ + } \ +} while (0) + +#define SLIST_EMPTY(head) ((head)->slh_first == NULL) + +#define SLIST_FIRST(head) ((head)->slh_first) + +#define SLIST_FOREACH(var, head, field) \ + for ((var) = SLIST_FIRST((head)); \ + (var); \ + (var) = SLIST_NEXT((var), field)) + +#define SLIST_FOREACH_FROM(var, head, field) \ + for ((var) = ((var) ? (var) : SLIST_FIRST((head))); \ + (var); \ + (var) = SLIST_NEXT((var), field)) + +#define SLIST_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = SLIST_FIRST((head)); \ + (var) && ((tvar) = SLIST_NEXT((var), field), 1); \ + (var) = (tvar)) + +#define SLIST_FOREACH_FROM_SAFE(var, head, field, tvar) \ + for ((var) = ((var) ? (var) : SLIST_FIRST((head))); \ + (var) && ((tvar) = SLIST_NEXT((var), field), 1); \ + (var) = (tvar)) + +#define SLIST_FOREACH_PREVPTR(var, varp, head, field) \ + for ((varp) = &SLIST_FIRST((head)); \ + ((var) = *(varp)) != NULL; \ + (varp) = &SLIST_NEXT((var), field)) + +#define SLIST_INIT(head) do { \ + SLIST_FIRST((head)) = NULL; \ +} while (0) + +#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \ + SLIST_NEXT((elm), field) = SLIST_NEXT((slistelm), field); \ + SLIST_NEXT((slistelm), field) = (elm); \ +} while (0) + +#define SLIST_INSERT_HEAD(head, elm, field) do { \ + SLIST_NEXT((elm), field) = SLIST_FIRST((head)); \ + SLIST_FIRST((head)) = (elm); \ +} while (0) + +#define SLIST_NEXT(elm, field) ((elm)->field.sle_next) + +#define SLIST_REMOVE(head, elm, type, field) do { \ + QMD_SAVELINK(oldnext, (elm)->field.sle_next); \ + if (SLIST_FIRST((head)) == (elm)) { \ + SLIST_REMOVE_HEAD((head), field); \ + } \ + else { \ + QUEUE_TYPEOF(type) *curelm = SLIST_FIRST(head); \ + while (SLIST_NEXT(curelm, field) != (elm)) \ + curelm = SLIST_NEXT(curelm, field); \ + SLIST_REMOVE_AFTER(curelm, field); \ + } \ + TRASHIT(*oldnext); \ +} while (0) + +#define SLIST_REMOVE_AFTER(elm, field) do { \ + SLIST_NEXT(elm, field) = \ + SLIST_NEXT(SLIST_NEXT(elm, field), field); \ +} while (0) + +#define SLIST_REMOVE_HEAD(head, field) do { \ + SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field); \ +} while (0) + +#define SLIST_REMOVE_PREVPTR(prevp, elm, field) do { \ + QMD_SLIST_CHECK_PREVPTR(prevp, elm); \ + *(prevp) = SLIST_NEXT(elm, field); \ + TRASHIT((elm)->field.sle_next); \ +} while (0) + +#define SLIST_SWAP(head1, head2, type) do { \ + QUEUE_TYPEOF(type) *swap_first = SLIST_FIRST(head1); \ + SLIST_FIRST(head1) = SLIST_FIRST(head2); \ + SLIST_FIRST(head2) = swap_first; \ +} while (0) + +/* + * Singly-linked Tail queue declarations. + */ +#define STAILQ_HEAD(name, type) \ +struct name { \ + struct type *stqh_first;/* first element */ \ + struct type **stqh_last;/* addr of last next element */ \ +} + +#define STAILQ_CLASS_HEAD(name, type) \ +struct name { \ + class type *stqh_first; /* first element */ \ + class type **stqh_last; /* addr of last next element */ \ +} + +#define STAILQ_HEAD_INITIALIZER(head) \ + { NULL, &(head).stqh_first } + +#define STAILQ_ENTRY(type) \ +struct { \ + struct type *stqe_next; /* next element */ \ +} + +#define STAILQ_CLASS_ENTRY(type) \ +struct { \ + class type *stqe_next; /* next element */ \ +} + +/* + * Singly-linked Tail queue functions. + */ +#define STAILQ_CONCAT(head1, head2) do { \ + if (!STAILQ_EMPTY((head2))) { \ + *(head1)->stqh_last = (head2)->stqh_first; \ + (head1)->stqh_last = (head2)->stqh_last; \ + STAILQ_INIT((head2)); \ + } \ +} while (0) + +#define STAILQ_EMPTY(head) ((head)->stqh_first == NULL) + +#define STAILQ_FIRST(head) ((head)->stqh_first) + +#define STAILQ_FOREACH(var, head, field) \ + for((var) = STAILQ_FIRST((head)); \ + (var); \ + (var) = STAILQ_NEXT((var), field)) + +#define STAILQ_FOREACH_FROM(var, head, field) \ + for ((var) = ((var) ? (var) : STAILQ_FIRST((head))); \ + (var); \ + (var) = STAILQ_NEXT((var), field)) + +#define STAILQ_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = STAILQ_FIRST((head)); \ + (var) && ((tvar) = STAILQ_NEXT((var), field), 1); \ + (var) = (tvar)) + +#define STAILQ_FOREACH_FROM_SAFE(var, head, field, tvar) \ + for ((var) = ((var) ? (var) : STAILQ_FIRST((head))); \ + (var) && ((tvar) = STAILQ_NEXT((var), field), 1); \ + (var) = (tvar)) + +#define STAILQ_INIT(head) do { \ + STAILQ_FIRST((head)) = NULL; \ + (head)->stqh_last = &STAILQ_FIRST((head)); \ +} while (0) + +#define STAILQ_INSERT_AFTER(head, tqelm, elm, field) do { \ + if ((STAILQ_NEXT((elm), field) = STAILQ_NEXT((tqelm), field)) == NULL)\ + (head)->stqh_last = &STAILQ_NEXT((elm), field); \ + STAILQ_NEXT((tqelm), field) = (elm); \ +} while (0) + +#define STAILQ_INSERT_HEAD(head, elm, field) do { \ + if ((STAILQ_NEXT((elm), field) = STAILQ_FIRST((head))) == NULL) \ + (head)->stqh_last = &STAILQ_NEXT((elm), field); \ + STAILQ_FIRST((head)) = (elm); \ +} while (0) + +#define STAILQ_INSERT_TAIL(head, elm, field) do { \ + STAILQ_NEXT((elm), field) = NULL; \ + *(head)->stqh_last = (elm); \ + (head)->stqh_last = &STAILQ_NEXT((elm), field); \ +} while (0) + +#define STAILQ_LAST(head, type, field) \ + (STAILQ_EMPTY((head)) ? NULL : \ + __containerof((head)->stqh_last, \ + QUEUE_TYPEOF(type), field.stqe_next)) + +#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next) + +#define STAILQ_REMOVE(head, elm, type, field) do { \ + QMD_SAVELINK(oldnext, (elm)->field.stqe_next); \ + if (STAILQ_FIRST((head)) == (elm)) { \ + STAILQ_REMOVE_HEAD((head), field); \ + } \ + else { \ + QUEUE_TYPEOF(type) *curelm = STAILQ_FIRST(head); \ + while (STAILQ_NEXT(curelm, field) != (elm)) \ + curelm = STAILQ_NEXT(curelm, field); \ + STAILQ_REMOVE_AFTER(head, curelm, field); \ + } \ + TRASHIT(*oldnext); \ +} while (0) + +#define STAILQ_REMOVE_AFTER(head, elm, field) do { \ + if ((STAILQ_NEXT(elm, field) = \ + STAILQ_NEXT(STAILQ_NEXT(elm, field), field)) == NULL) \ + (head)->stqh_last = &STAILQ_NEXT((elm), field); \ +} while (0) + +#define STAILQ_REMOVE_HEAD(head, field) do { \ + if ((STAILQ_FIRST((head)) = \ + STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL) \ + (head)->stqh_last = &STAILQ_FIRST((head)); \ +} while (0) + +#define STAILQ_SWAP(head1, head2, type) do { \ + QUEUE_TYPEOF(type) *swap_first = STAILQ_FIRST(head1); \ + QUEUE_TYPEOF(type) **swap_last = (head1)->stqh_last; \ + STAILQ_FIRST(head1) = STAILQ_FIRST(head2); \ + (head1)->stqh_last = (head2)->stqh_last; \ + STAILQ_FIRST(head2) = swap_first; \ + (head2)->stqh_last = swap_last; \ + if (STAILQ_EMPTY(head1)) \ + (head1)->stqh_last = &STAILQ_FIRST(head1); \ + if (STAILQ_EMPTY(head2)) \ + (head2)->stqh_last = &STAILQ_FIRST(head2); \ +} while (0) + + +/* + * List declarations. + */ +#define LIST_HEAD(name, type) \ +struct name { \ + struct type *lh_first; /* first element */ \ +} + +#define LIST_CLASS_HEAD(name, type) \ +struct name { \ + class type *lh_first; /* first element */ \ +} + +#define LIST_HEAD_INITIALIZER(head) \ + { NULL } + +#define LIST_ENTRY(type) \ +struct { \ + struct type *le_next; /* next element */ \ + struct type **le_prev; /* address of previous next element */ \ +} + +#define LIST_CLASS_ENTRY(type) \ +struct { \ + class type *le_next; /* next element */ \ + class type **le_prev; /* address of previous next element */ \ +} + +/* + * List functions. + */ + +#if (defined(_KERNEL) && defined(INVARIANTS)) +/* + * QMD_LIST_CHECK_HEAD(LIST_HEAD *head, LIST_ENTRY NAME) + * + * If the list is non-empty, validates that the first element of the list + * points back at 'head.' + */ +#define QMD_LIST_CHECK_HEAD(head, field) do { \ + if (LIST_FIRST((head)) != NULL && \ + LIST_FIRST((head))->field.le_prev != \ + &LIST_FIRST((head))) \ + panic("Bad list head %p first->prev != head", (head)); \ +} while (0) + +/* + * QMD_LIST_CHECK_NEXT(TYPE *elm, LIST_ENTRY NAME) + * + * If an element follows 'elm' in the list, validates that the next element + * points back at 'elm.' + */ +#define QMD_LIST_CHECK_NEXT(elm, field) do { \ + if (LIST_NEXT((elm), field) != NULL && \ + LIST_NEXT((elm), field)->field.le_prev != \ + &((elm)->field.le_next)) \ + panic("Bad link elm %p next->prev != elm", (elm)); \ +} while (0) + +/* + * QMD_LIST_CHECK_PREV(TYPE *elm, LIST_ENTRY NAME) + * + * Validates that the previous element (or head of the list) points to 'elm.' + */ +#define QMD_LIST_CHECK_PREV(elm, field) do { \ + if (*(elm)->field.le_prev != (elm)) \ + panic("Bad link elm %p prev->next != elm", (elm)); \ +} while (0) +#else +#define QMD_LIST_CHECK_HEAD(head, field) +#define QMD_LIST_CHECK_NEXT(elm, field) +#define QMD_LIST_CHECK_PREV(elm, field) +#endif /* (_KERNEL && INVARIANTS) */ + +#define LIST_CONCAT(head1, head2, type, field) do { \ + QUEUE_TYPEOF(type) *curelm = LIST_FIRST(head1); \ + if (curelm == NULL) { \ + if ((LIST_FIRST(head1) = LIST_FIRST(head2)) != NULL) { \ + LIST_FIRST(head2)->field.le_prev = \ + &LIST_FIRST((head1)); \ + LIST_INIT(head2); \ + } \ + } else if (LIST_FIRST(head2) != NULL) { \ + while (LIST_NEXT(curelm, field) != NULL) \ + curelm = LIST_NEXT(curelm, field); \ + LIST_NEXT(curelm, field) = LIST_FIRST(head2); \ + LIST_FIRST(head2)->field.le_prev = &LIST_NEXT(curelm, field); \ + LIST_INIT(head2); \ + } \ +} while (0) + +#define LIST_EMPTY(head) ((head)->lh_first == NULL) + +#define LIST_FIRST(head) ((head)->lh_first) + +#define LIST_FOREACH(var, head, field) \ + for ((var) = LIST_FIRST((head)); \ + (var); \ + (var) = LIST_NEXT((var), field)) + +#define LIST_FOREACH_FROM(var, head, field) \ + for ((var) = ((var) ? (var) : LIST_FIRST((head))); \ + (var); \ + (var) = LIST_NEXT((var), field)) + +#define LIST_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = LIST_FIRST((head)); \ + (var) && ((tvar) = LIST_NEXT((var), field), 1); \ + (var) = (tvar)) + +#define LIST_FOREACH_FROM_SAFE(var, head, field, tvar) \ + for ((var) = ((var) ? (var) : LIST_FIRST((head))); \ + (var) && ((tvar) = LIST_NEXT((var), field), 1); \ + (var) = (tvar)) + +#define LIST_INIT(head) do { \ + LIST_FIRST((head)) = NULL; \ +} while (0) + +#define LIST_INSERT_AFTER(listelm, elm, field) do { \ + QMD_LIST_CHECK_NEXT(listelm, field); \ + if ((LIST_NEXT((elm), field) = LIST_NEXT((listelm), field)) != NULL)\ + LIST_NEXT((listelm), field)->field.le_prev = \ + &LIST_NEXT((elm), field); \ + LIST_NEXT((listelm), field) = (elm); \ + (elm)->field.le_prev = &LIST_NEXT((listelm), field); \ +} while (0) + +#define LIST_INSERT_BEFORE(listelm, elm, field) do { \ + QMD_LIST_CHECK_PREV(listelm, field); \ + (elm)->field.le_prev = (listelm)->field.le_prev; \ + LIST_NEXT((elm), field) = (listelm); \ + *(listelm)->field.le_prev = (elm); \ + (listelm)->field.le_prev = &LIST_NEXT((elm), field); \ +} while (0) + +#define LIST_INSERT_HEAD(head, elm, field) do { \ + QMD_LIST_CHECK_HEAD((head), field); \ + if ((LIST_NEXT((elm), field) = LIST_FIRST((head))) != NULL) \ + LIST_FIRST((head))->field.le_prev = &LIST_NEXT((elm), field);\ + LIST_FIRST((head)) = (elm); \ + (elm)->field.le_prev = &LIST_FIRST((head)); \ +} while (0) + +#define LIST_NEXT(elm, field) ((elm)->field.le_next) + +#define LIST_PREV(elm, head, type, field) \ + ((elm)->field.le_prev == &LIST_FIRST((head)) ? NULL : \ + __containerof((elm)->field.le_prev, \ + QUEUE_TYPEOF(type), field.le_next)) + +#define LIST_REMOVE(elm, field) do { \ + QMD_SAVELINK(oldnext, (elm)->field.le_next); \ + QMD_SAVELINK(oldprev, (elm)->field.le_prev); \ + QMD_LIST_CHECK_NEXT(elm, field); \ + QMD_LIST_CHECK_PREV(elm, field); \ + if (LIST_NEXT((elm), field) != NULL) \ + LIST_NEXT((elm), field)->field.le_prev = \ + (elm)->field.le_prev; \ + *(elm)->field.le_prev = LIST_NEXT((elm), field); \ + TRASHIT(*oldnext); \ + TRASHIT(*oldprev); \ +} while (0) + +#define LIST_SWAP(head1, head2, type, field) do { \ + QUEUE_TYPEOF(type) *swap_tmp = LIST_FIRST(head1); \ + LIST_FIRST((head1)) = LIST_FIRST((head2)); \ + LIST_FIRST((head2)) = swap_tmp; \ + if ((swap_tmp = LIST_FIRST((head1))) != NULL) \ + swap_tmp->field.le_prev = &LIST_FIRST((head1)); \ + if ((swap_tmp = LIST_FIRST((head2))) != NULL) \ + swap_tmp->field.le_prev = &LIST_FIRST((head2)); \ +} while (0) + +/* + * Tail queue declarations. + */ +#define TAILQ_HEAD(name, type) \ +struct name { \ + struct type *tqh_first; /* first element */ \ + struct type **tqh_last; /* addr of last next element */ \ + TRACEBUF \ +} + +#define TAILQ_CLASS_HEAD(name, type) \ +struct name { \ + class type *tqh_first; /* first element */ \ + class type **tqh_last; /* addr of last next element */ \ + TRACEBUF \ +} + +#define TAILQ_HEAD_INITIALIZER(head) \ + { NULL, &(head).tqh_first, TRACEBUF_INITIALIZER } + +#define TAILQ_ENTRY(type) \ +struct { \ + struct type *tqe_next; /* next element */ \ + struct type **tqe_prev; /* address of previous next element */ \ + TRACEBUF \ +} + +#define TAILQ_CLASS_ENTRY(type) \ +struct { \ + class type *tqe_next; /* next element */ \ + class type **tqe_prev; /* address of previous next element */ \ + TRACEBUF \ +} + +/* + * Tail queue functions. + */ +#if (defined(_KERNEL) && defined(INVARIANTS)) +/* + * QMD_TAILQ_CHECK_HEAD(TAILQ_HEAD *head, TAILQ_ENTRY NAME) + * + * If the tailq is non-empty, validates that the first element of the tailq + * points back at 'head.' + */ +#define QMD_TAILQ_CHECK_HEAD(head, field) do { \ + if (!TAILQ_EMPTY(head) && \ + TAILQ_FIRST((head))->field.tqe_prev != \ + &TAILQ_FIRST((head))) \ + panic("Bad tailq head %p first->prev != head", (head)); \ +} while (0) + +/* + * QMD_TAILQ_CHECK_TAIL(TAILQ_HEAD *head, TAILQ_ENTRY NAME) + * + * Validates that the tail of the tailq is a pointer to pointer to NULL. + */ +#define QMD_TAILQ_CHECK_TAIL(head, field) do { \ + if (*(head)->tqh_last != NULL) \ + panic("Bad tailq NEXT(%p->tqh_last) != NULL", (head)); \ +} while (0) + +/* + * QMD_TAILQ_CHECK_NEXT(TYPE *elm, TAILQ_ENTRY NAME) + * + * If an element follows 'elm' in the tailq, validates that the next element + * points back at 'elm.' + */ +#define QMD_TAILQ_CHECK_NEXT(elm, field) do { \ + if (TAILQ_NEXT((elm), field) != NULL && \ + TAILQ_NEXT((elm), field)->field.tqe_prev != \ + &((elm)->field.tqe_next)) \ + panic("Bad link elm %p next->prev != elm", (elm)); \ +} while (0) + +/* + * QMD_TAILQ_CHECK_PREV(TYPE *elm, TAILQ_ENTRY NAME) + * + * Validates that the previous element (or head of the tailq) points to 'elm.' + */ +#define QMD_TAILQ_CHECK_PREV(elm, field) do { \ + if (*(elm)->field.tqe_prev != (elm)) \ + panic("Bad link elm %p prev->next != elm", (elm)); \ +} while (0) +#else +#define QMD_TAILQ_CHECK_HEAD(head, field) +#define QMD_TAILQ_CHECK_TAIL(head, headname) +#define QMD_TAILQ_CHECK_NEXT(elm, field) +#define QMD_TAILQ_CHECK_PREV(elm, field) +#endif /* (_KERNEL && INVARIANTS) */ + +#define TAILQ_CONCAT(head1, head2, field) do { \ + if (!TAILQ_EMPTY(head2)) { \ + *(head1)->tqh_last = (head2)->tqh_first; \ + (head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \ + (head1)->tqh_last = (head2)->tqh_last; \ + TAILQ_INIT((head2)); \ + QMD_TRACE_HEAD(head1); \ + QMD_TRACE_HEAD(head2); \ + } \ +} while (0) + +#define TAILQ_EMPTY(head) ((head)->tqh_first == NULL) + +#define TAILQ_FIRST(head) ((head)->tqh_first) + +#define TAILQ_FOREACH(var, head, field) \ + for ((var) = TAILQ_FIRST((head)); \ + (var); \ + (var) = TAILQ_NEXT((var), field)) + +#define TAILQ_FOREACH_FROM(var, head, field) \ + for ((var) = ((var) ? (var) : TAILQ_FIRST((head))); \ + (var); \ + (var) = TAILQ_NEXT((var), field)) + +#define TAILQ_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = TAILQ_FIRST((head)); \ + (var) && ((tvar) = TAILQ_NEXT((var), field), 1); \ + (var) = (tvar)) + +#define TAILQ_FOREACH_FROM_SAFE(var, head, field, tvar) \ + for ((var) = ((var) ? (var) : TAILQ_FIRST((head))); \ + (var) && ((tvar) = TAILQ_NEXT((var), field), 1); \ + (var) = (tvar)) + +#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \ + for ((var) = TAILQ_LAST((head), headname); \ + (var); \ + (var) = TAILQ_PREV((var), headname, field)) + +#define TAILQ_FOREACH_REVERSE_FROM(var, head, headname, field) \ + for ((var) = ((var) ? (var) : TAILQ_LAST((head), headname)); \ + (var); \ + (var) = TAILQ_PREV((var), headname, field)) + +#define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \ + for ((var) = TAILQ_LAST((head), headname); \ + (var) && ((tvar) = TAILQ_PREV((var), headname, field), 1); \ + (var) = (tvar)) + +#define TAILQ_FOREACH_REVERSE_FROM_SAFE(var, head, headname, field, tvar) \ + for ((var) = ((var) ? (var) : TAILQ_LAST((head), headname)); \ + (var) && ((tvar) = TAILQ_PREV((var), headname, field), 1); \ + (var) = (tvar)) + +#define TAILQ_INIT(head) do { \ + TAILQ_FIRST((head)) = NULL; \ + (head)->tqh_last = &TAILQ_FIRST((head)); \ + QMD_TRACE_HEAD(head); \ +} while (0) + +#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \ + QMD_TAILQ_CHECK_NEXT(listelm, field); \ + if ((TAILQ_NEXT((elm), field) = TAILQ_NEXT((listelm), field)) != NULL)\ + TAILQ_NEXT((elm), field)->field.tqe_prev = \ + &TAILQ_NEXT((elm), field); \ + else { \ + (head)->tqh_last = &TAILQ_NEXT((elm), field); \ + QMD_TRACE_HEAD(head); \ + } \ + TAILQ_NEXT((listelm), field) = (elm); \ + (elm)->field.tqe_prev = &TAILQ_NEXT((listelm), field); \ + QMD_TRACE_ELEM(&(elm)->field); \ + QMD_TRACE_ELEM(&(listelm)->field); \ +} while (0) + +#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \ + QMD_TAILQ_CHECK_PREV(listelm, field); \ + (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \ + TAILQ_NEXT((elm), field) = (listelm); \ + *(listelm)->field.tqe_prev = (elm); \ + (listelm)->field.tqe_prev = &TAILQ_NEXT((elm), field); \ + QMD_TRACE_ELEM(&(elm)->field); \ + QMD_TRACE_ELEM(&(listelm)->field); \ +} while (0) + +#define TAILQ_INSERT_HEAD(head, elm, field) do { \ + QMD_TAILQ_CHECK_HEAD(head, field); \ + if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL) \ + TAILQ_FIRST((head))->field.tqe_prev = \ + &TAILQ_NEXT((elm), field); \ + else \ + (head)->tqh_last = &TAILQ_NEXT((elm), field); \ + TAILQ_FIRST((head)) = (elm); \ + (elm)->field.tqe_prev = &TAILQ_FIRST((head)); \ + QMD_TRACE_HEAD(head); \ + QMD_TRACE_ELEM(&(elm)->field); \ +} while (0) + +#define TAILQ_INSERT_TAIL(head, elm, field) do { \ + QMD_TAILQ_CHECK_TAIL(head, field); \ + TAILQ_NEXT((elm), field) = NULL; \ + (elm)->field.tqe_prev = (head)->tqh_last; \ + *(head)->tqh_last = (elm); \ + (head)->tqh_last = &TAILQ_NEXT((elm), field); \ + QMD_TRACE_HEAD(head); \ + QMD_TRACE_ELEM(&(elm)->field); \ +} while (0) + +#define TAILQ_LAST(head, headname) \ + (*(((struct headname *)((head)->tqh_last))->tqh_last)) + +/* + * The FAST function is fast in that it causes no data access other + * then the access to the head. The standard LAST function above + * will cause a data access of both the element you want and + * the previous element. FAST is very useful for instances when + * you may want to prefetch the last data element. + */ +#define TAILQ_LAST_FAST(head, type, field) \ + (TAILQ_EMPTY(head) ? NULL : __containerof((head)->tqh_last, QUEUE_TYPEOF(type), field.tqe_next)) + +#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) + +#define TAILQ_PREV(elm, headname, field) \ + (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last)) + +#define TAILQ_REMOVE(head, elm, field) do { \ + QMD_SAVELINK(oldnext, (elm)->field.tqe_next); \ + QMD_SAVELINK(oldprev, (elm)->field.tqe_prev); \ + QMD_TAILQ_CHECK_NEXT(elm, field); \ + QMD_TAILQ_CHECK_PREV(elm, field); \ + if ((TAILQ_NEXT((elm), field)) != NULL) \ + TAILQ_NEXT((elm), field)->field.tqe_prev = \ + (elm)->field.tqe_prev; \ + else { \ + (head)->tqh_last = (elm)->field.tqe_prev; \ + QMD_TRACE_HEAD(head); \ + } \ + *(elm)->field.tqe_prev = TAILQ_NEXT((elm), field); \ + TRASHIT(*oldnext); \ + TRASHIT(*oldprev); \ + QMD_TRACE_ELEM(&(elm)->field); \ +} while (0) + +#define TAILQ_SWAP(head1, head2, type, field) do { \ + QUEUE_TYPEOF(type) *swap_first = (head1)->tqh_first; \ + QUEUE_TYPEOF(type) **swap_last = (head1)->tqh_last; \ + (head1)->tqh_first = (head2)->tqh_first; \ + (head1)->tqh_last = (head2)->tqh_last; \ + (head2)->tqh_first = swap_first; \ + (head2)->tqh_last = swap_last; \ + if ((swap_first = (head1)->tqh_first) != NULL) \ + swap_first->field.tqe_prev = &(head1)->tqh_first; \ + else \ + (head1)->tqh_last = &(head1)->tqh_first; \ + if ((swap_first = (head2)->tqh_first) != NULL) \ + swap_first->field.tqe_prev = &(head2)->tqh_first; \ + else \ + (head2)->tqh_last = &(head2)->tqh_first; \ +} while (0) + +#endif /* !_SYS_QUEUE_H_ */ -- cgit v1.3.1 From c7340f4b0eb8dcf15fa93f6bf6589a94fb59dc95 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 23 Oct 2018 12:19:32 +0700 Subject: clean up helper func --- examples/obsolete/device/src/mouse_device_app.c | 2 +- examples/obsolete/host/src/cdc_serial_host_app.c | 4 +-- examples/obsolete/host/src/keyboard_host_app.c | 2 +- examples/obsolete/host/src/mouse_host_app.c | 2 +- examples/obsolete/host/src/msc_cli.c | 6 ++-- src/class/cdc/cdc_device.c | 4 +-- src/class/cdc/cdc_host.c | 4 +-- src/class/cdc/cdc_rndis_host.c | 8 ++--- src/class/custom/custom_device.c | 2 +- src/class/custom/custom_host.c | 4 +-- src/class/hid/hid_device.c | 8 ++--- src/class/hid/hid_host.c | 6 ++-- src/class/msc/msc_device.c | 12 ++++---- src/class/msc/msc_host.c | 4 +-- src/common/tusb_common.h | 34 +++------------------- src/device/usbd.c | 4 +-- src/host/ehci/ehci.c | 8 ++--- src/host/hub.c | 4 +-- src/host/ohci/ohci.c | 6 ++-- src/host/usbh.c | 2 +- src/osal/osal_mynewt.h | 2 +- src/portable/nordic/nrf5x/dcd_nrf5x.c | 2 +- .../nxp/lpc11xx_lpc13xx/dcd_lpc_11uxx_13uxx.c | 4 +-- src/portable/nxp/lpc17xx/dcd_lpc175x_6x.c | 6 ++-- src/portable/nxp/lpc43xx_lpc18xx/dcd_lpc43xx.c | 8 ++--- tests/lpc175x_6x/test/test_dcd_lpc175x_6x.c | 8 ++--- tests/lpc18xx_43xx/test/host/cdc/test_cdc_host.c | 2 +- .../test/host/ehci/test_pipe_bulk_open.c | 2 +- .../test/host/ehci/test_pipe_bulk_xfer.c | 4 +-- .../test/host/ehci/test_pipe_control_open.c | 2 +- .../test/host/ehci/test_pipe_control_xfer.c | 4 +-- .../test/host/ehci/test_pipe_interrupt_open.c | 4 +-- .../test/host/ehci/test_pipe_interrupt_xfer.c | 4 +-- .../test/host/ehci/test_pipe_isochronous_open.c | 2 +- .../test/host/hid/test_hidh_keyboard.c | 2 +- tests/lpc18xx_43xx/test/host/hid/test_hidh_mouse.c | 2 +- tests/lpc18xx_43xx/test/host/usbh/test_enum_task.c | 2 +- tests/support/ehci_controller_fake.c | 4 +-- tests/support/type_helper.h | 4 +-- 39 files changed, 83 insertions(+), 111 deletions(-) (limited to 'src/common') diff --git a/examples/obsolete/device/src/mouse_device_app.c b/examples/obsolete/device/src/mouse_device_app.c index d6145026a..077cecc7c 100644 --- a/examples/obsolete/device/src/mouse_device_app.c +++ b/examples/obsolete/device/src/mouse_device_app.c @@ -126,7 +126,7 @@ void mouse_app_subtask(void) enum { MOUSE_RESOLUTION = 5 }; uint32_t button_mask = board_buttons(); - memclr_(&mouse_report, sizeof(hid_mouse_report_t)); + tu_memclr(&mouse_report, sizeof(hid_mouse_report_t)); if ( BIT_TEST_(button_mask, BUTTON_UP ) ) mouse_report.y = -MOUSE_RESOLUTION; if ( BIT_TEST_(button_mask, BUTTON_DOWN ) ) mouse_report.y = MOUSE_RESOLUTION; diff --git a/examples/obsolete/host/src/cdc_serial_host_app.c b/examples/obsolete/host/src/cdc_serial_host_app.c index e21a3a67d..30ed6698e 100644 --- a/examples/obsolete/host/src/cdc_serial_host_app.c +++ b/examples/obsolete/host/src/cdc_serial_host_app.c @@ -61,8 +61,8 @@ void tuh_cdc_mounted_cb(uint8_t dev_addr) { // application set-up printf("\na CDC device (address %d) is mounted\n", dev_addr); - memclr_(serial_in_buffer, sizeof(serial_in_buffer)); - memclr_(serial_out_buffer, sizeof(serial_out_buffer)); + tu_memclr(serial_in_buffer, sizeof(serial_in_buffer)); + tu_memclr(serial_out_buffer, sizeof(serial_out_buffer)); received_bytes = 0; osal_semaphore_reset(sem_hdl); diff --git a/examples/obsolete/host/src/keyboard_host_app.c b/examples/obsolete/host/src/keyboard_host_app.c index 26b1a0800..21ace3bbf 100644 --- a/examples/obsolete/host/src/keyboard_host_app.c +++ b/examples/obsolete/host/src/keyboard_host_app.c @@ -100,7 +100,7 @@ void tuh_hid_keyboard_isr(uint8_t dev_addr, tusb_event_t event) //--------------------------------------------------------------------+ void keyboard_host_app_init(void) { - memclr_(&usb_keyboard_report, sizeof(hid_keyboard_report_t)); + tu_memclr(&usb_keyboard_report, sizeof(hid_keyboard_report_t)); queue_kbd_hdl = osal_queue_create( QUEUE_KEYBOARD_REPORT_DEPTH, sizeof(hid_keyboard_report_t) ); TU_ASSERT( queue_kbd_hdl, VOID_RETURN ); diff --git a/examples/obsolete/host/src/mouse_host_app.c b/examples/obsolete/host/src/mouse_host_app.c index c326becb8..e242c7caa 100644 --- a/examples/obsolete/host/src/mouse_host_app.c +++ b/examples/obsolete/host/src/mouse_host_app.c @@ -101,7 +101,7 @@ void tuh_hid_mouse_isr(uint8_t dev_addr, tusb_event_t event) //--------------------------------------------------------------------+ void mouse_host_app_init(void) { - memclr_(&usb_mouse_report, sizeof(hid_mouse_report_t)); + tu_memclr(&usb_mouse_report, sizeof(hid_mouse_report_t)); queue_mouse_hdl = osal_queue_create( QUEUE_MOUSE_REPORT_DEPTH, sizeof(hid_mouse_report_t) ); TU_ASSERT( queue_mouse_hdl, VOID_RETURN); diff --git a/examples/obsolete/host/src/msc_cli.c b/examples/obsolete/host/src/msc_cli.c index 0182a6df9..1f7b1f5ec 100644 --- a/examples/obsolete/host/src/msc_cli.c +++ b/examples/obsolete/host/src/msc_cli.c @@ -176,12 +176,12 @@ void cli_command_prompt(void) (volume_label[0] !=0) ? volume_label : "No Label", cli_buffer); - memclr_(cli_buffer, CLI_MAX_BUFFER); + tu_memclr(cli_buffer, CLI_MAX_BUFFER); } void cli_init(void) { - memclr_(cli_buffer, CLI_MAX_BUFFER); + tu_memclr(cli_buffer, CLI_MAX_BUFFER); f_getlabel(NULL, volume_label, NULL); cli_command_prompt(); } @@ -197,7 +197,7 @@ void cli_poll(char ch) }else { puts("cli buffer overflows"); - memclr_(cli_buffer, CLI_MAX_BUFFER); + tu_memclr(cli_buffer, CLI_MAX_BUFFER); } } else if ( ch == ASCII_BACKSPACE && strlen(cli_buffer)) diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index 70d51c258..06530bc7a 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -185,7 +185,7 @@ bool tud_cdc_n_write_flush (uint8_t itf) //--------------------------------------------------------------------+ void cdcd_init(void) { - arrclr_( _cdcd_itf ); + tu_memclr(_cdcd_itf, sizeof(_cdcd_itf)); for(uint8_t i=0; ipipe_in); (void) hcd_pipe_close(p_cdc->pipe_out); - memclr_(p_cdc, sizeof(cdch_data_t)); + tu_memclr(p_cdc, sizeof(cdch_data_t)); tuh_cdc_unmounted_cb(dev_addr); diff --git a/src/class/cdc/cdc_rndis_host.c b/src/class/cdc/cdc_rndis_host.c index 4d28b0e0c..9b7684f77 100644 --- a/src/class/cdc/cdc_rndis_host.c +++ b/src/class/cdc/cdc_rndis_host.c @@ -117,7 +117,7 @@ static tusb_error_t rndis_body_subtask(void) //--------------------------------------------------------------------+ void rndish_init(void) { - memclr_(rndish_data, sizeof(rndish_data_t)*CFG_TUSB_HOST_DEVICE_MAX); + tu_memclr(rndish_data, sizeof(rndish_data_t)*CFG_TUSB_HOST_DEVICE_MAX); //------------- Task creation -------------// @@ -131,7 +131,7 @@ void rndish_init(void) void rndish_close(uint8_t dev_addr) { osal_semaphore_reset( rndish_data[dev_addr-1].sem_notification_hdl ); -// memclr_(&rndish_data[dev_addr-1], sizeof(rndish_data_t)); TODO need to move semaphore & its handle out before memclr +// tu_memclr(&rndish_data[dev_addr-1], sizeof(rndish_data_t)); TODO need to move semaphore & its handle out before memclr } @@ -189,7 +189,7 @@ tusb_error_t rndish_open_subtask(uint8_t dev_addr, cdch_data_t *p_cdc) //------------- Message Query 802.3 Permanent Address -------------// memcpy(msg_payload, &msg_query_permanent_addr, sizeof(rndis_msg_query_t)); - memclr_(msg_payload + sizeof(rndis_msg_query_t), 6); // 6 bytes for MAC address + tu_memclr(msg_payload + sizeof(rndis_msg_query_t), 6); // 6 bytes for MAC address STASK_INVOKE( send_message_get_response_subtask( dev_addr, p_cdc, @@ -205,7 +205,7 @@ tusb_error_t rndish_open_subtask(uint8_t dev_addr, cdch_data_t *p_cdc) //------------- Set OID_GEN_CURRENT_PACKET_FILTER to (DIRECTED | MULTICAST | BROADCAST) -------------// memcpy(msg_payload, &msg_set_packet_filter, sizeof(rndis_msg_set_t)); - memclr_(msg_payload + sizeof(rndis_msg_set_t), 4); // 4 bytes for filter flags + tu_memclr(msg_payload + sizeof(rndis_msg_set_t), 4); // 4 bytes for filter flags ((rndis_msg_set_t*) msg_payload)->oid_buffer[0] = (RNDIS_PACKET_TYPE_DIRECTED | RNDIS_PACKET_TYPE_MULTICAST | RNDIS_PACKET_TYPE_BROADCAST); STASK_INVOKE( diff --git a/src/class/custom/custom_device.c b/src/class/custom/custom_device.c index 2c3783e35..d43a86b14 100644 --- a/src/class/custom/custom_device.c +++ b/src/class/custom/custom_device.c @@ -68,7 +68,7 @@ static cusd_interface_t _cusd_itf; *------------------------------------------------------------------*/ void cusd_init(void) { - varclr_(&_cusd_itf); + tu_varclr(&_cusd_itf); } tusb_error_t cusd_open(uint8_t rhport, tusb_desc_interface_t const * p_desc_itf, uint16_t *p_len) diff --git a/src/class/custom/custom_host.c b/src/class/custom/custom_host.c index ad3315980..329012fda 100644 --- a/src/class/custom/custom_host.c +++ b/src/class/custom/custom_host.c @@ -104,7 +104,7 @@ tusb_error_t tusbh_custom_write(uint8_t dev_addr, uint16_t vendor_id, uint16_t p //--------------------------------------------------------------------+ void cush_init(void) { - memclr_(&custom_interface, sizeof(custom_interface_info_t) * CFG_TUSB_HOST_DEVICE_MAX); + tu_memclr(&custom_interface, sizeof(custom_interface_info_t) * CFG_TUSB_HOST_DEVICE_MAX); } tusb_error_t cush_open_subtask(uint8_t dev_addr, tusb_desc_interface_t const *p_interface_desc, uint16_t *p_length) @@ -152,7 +152,7 @@ void cush_close(uint8_t dev_addr) err2 = hcd_pipe_close( p_interface->pipe_out ); } - memclr_(p_interface, sizeof(custom_interface_info_t)); + tu_memclr(p_interface, sizeof(custom_interface_info_t)); TU_ASSERT(err1 == TUSB_ERROR_NONE && err2 == TUSB_ERROR_NONE, (void) 0 ); } diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index b1cd1d1bd..d8696f137 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -188,7 +188,7 @@ bool tud_hid_keyboard_keycode(uint8_t modifier, uint8_t keycode[6]) memcpy(report.keycode, keycode, 6); }else { - memclr_(report.keycode, 6); + tu_memclr(report.keycode, 6); } return hidd_kbd_report(&report); @@ -307,14 +307,14 @@ void hidd_init(void) void hidd_reset(uint8_t rhport) { - arrclr_(_hidd_itf); + tu_memclr(_hidd_itf, sizeof(_hidd_itf)); #if CFG_TUD_HID_KEYBOARD - varclr_(&_kbd_rpt); + tu_varclr(&_kbd_rpt); #endif #if CFG_TUD_HID_MOUSE - varclr_(&_mse_rpt); + tu_varclr(&_mse_rpt); #endif } diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 369dad638..518297eec 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -68,7 +68,7 @@ static inline tusb_error_t hidh_interface_open(uint8_t dev_addr, uint8_t interfa static inline void hidh_interface_close(hidh_interface_info_t *p_hid) { (void) hcd_pipe_close(p_hid->pipe_hdl); - memclr_(p_hid, sizeof(hidh_interface_info_t)); + tu_memclr(p_hid, sizeof(hidh_interface_info_t)); } // called from public API need to validate parameters @@ -164,11 +164,11 @@ tusb_error_t tuh_hid_mouse_get_report(uint8_t dev_addr, void * report) void hidh_init(void) { #if CFG_TUSB_HOST_HID_KEYBOARD - memclr_(&keyboardh_data, sizeof(hidh_interface_info_t)*CFG_TUSB_HOST_DEVICE_MAX); + tu_memclr(&keyboardh_data, sizeof(hidh_interface_info_t)*CFG_TUSB_HOST_DEVICE_MAX); #endif #if CFG_TUSB_HOST_HID_MOUSE - memclr_(&mouseh_data, sizeof(hidh_interface_info_t)*CFG_TUSB_HOST_DEVICE_MAX); + tu_memclr(&mouseh_data, sizeof(hidh_interface_info_t)*CFG_TUSB_HOST_DEVICE_MAX); #endif #if CFG_TUSB_HOST_HID_GENERIC diff --git a/src/class/msc/msc_device.c b/src/class/msc/msc_device.c index 3335ad9b3..830ce85b7 100644 --- a/src/class/msc/msc_device.c +++ b/src/class/msc/msc_device.c @@ -62,9 +62,9 @@ enum typedef struct { CFG_TUSB_MEM_ALIGN msc_cbw_t cbw; -#if defined (__ICCARM__) && (CFG_TUSB_MCU == OPT_MCU_LPC11UXX || CFG_TUSB_MCU == OPT_MCU_LPC13UXX) - uint8_t padding1[64-sizeof(msc_cbw_t)]; // IAR cannot align struct's member -#endif +//#if defined (__ICCARM__) && (CFG_TUSB_MCU == OPT_MCU_LPC11UXX || CFG_TUSB_MCU == OPT_MCU_LPC13UXX) +// uint8_t padding1[64-sizeof(msc_cbw_t)]; // IAR cannot align struct's member +//#endif CFG_TUSB_MEM_ALIGN msc_csw_t csw; @@ -141,12 +141,12 @@ bool tud_msc_set_sense(uint8_t lun, uint8_t sense_key, uint8_t add_sense_code, u //--------------------------------------------------------------------+ void mscd_init(void) { - memclr_(&_mscd_itf, sizeof(mscd_interface_t)); + tu_memclr(&_mscd_itf, sizeof(mscd_interface_t)); } void mscd_reset(uint8_t rhport) { - memclr_(&_mscd_itf, sizeof(mscd_interface_t)); + tu_memclr(&_mscd_itf, sizeof(mscd_interface_t)); } tusb_error_t mscd_open(uint8_t rhport, tusb_desc_interface_t const * p_desc_itf, uint16_t *p_len) @@ -302,7 +302,6 @@ tusb_error_t mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, tusb_event_t event, u { case MSC_STAGE_CMD: //------------- new CBW received -------------// - // Complete IN while waiting for CMD is usually Status of previous SCSI op, ignore it if(ep_addr != p_msc->ep_out) return TUSB_ERROR_NONE; @@ -332,7 +331,6 @@ tusb_error_t mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, tusb_event_t event, u // 1. Zero : Invoke app callback, skip DATA and move to STATUS stage // 2. OUT : queue transfer (invoke app callback after done) // 3. IN : invoke app callback to get response - if ( p_cbw->xfer_bytes == 0) { int32_t const cb_result = tud_msc_scsi_cb(p_cbw->lun, p_cbw->command, NULL, 0); diff --git a/src/class/msc/msc_host.c b/src/class/msc/msc_host.c index 7e6396389..9250b8df7 100644 --- a/src/class/msc/msc_host.c +++ b/src/class/msc/msc_host.c @@ -288,7 +288,7 @@ tusb_error_t tuh_msc_write10(uint8_t dev_addr, uint8_t lun, void const * p_buffe //--------------------------------------------------------------------+ void msch_init(void) { - memclr_(msch_data, sizeof(msch_interface_t)*CFG_TUSB_HOST_DEVICE_MAX); + tu_memclr(msch_data, sizeof(msch_interface_t)*CFG_TUSB_HOST_DEVICE_MAX); msch_sem_hdl = osal_semaphore_create(1, 0); } @@ -416,7 +416,7 @@ void msch_close(uint8_t dev_addr) (void) hcd_pipe_close(msch_data[dev_addr-1].bulk_in); (void) hcd_pipe_close(msch_data[dev_addr-1].bulk_out); - memclr_(&msch_data[dev_addr-1], sizeof(msch_interface_t)); + tu_memclr(&msch_data[dev_addr-1], sizeof(msch_interface_t)); osal_semaphore_reset(msch_sem_hdl); tuh_msc_unmounted_cb(dev_addr); // invoke Application Callback diff --git a/src/common/tusb_common.h b/src/common/tusb_common.h index 778e70676..85bd15d43 100644 --- a/src/common/tusb_common.h +++ b/src/common/tusb_common.h @@ -73,8 +73,7 @@ //--------------------------------------------------------------------+ // MACROS //--------------------------------------------------------------------+ -#define MAX_OF(a, b) ( (a) > (b) ? (a) : (b) ) -#define MIN_OF(a, b) ( (a) < (b) ? (a) : (b) ) +#define TU_ARRAY_SZIE(_arr) ( sizeof(_arr) / sizeof(_arr[0]) ) #define U16_HIGH_U8(u16) ((uint8_t) (((u16) >> 8) & 0x00ff)) #define U16_LOW_U8(u16) ((uint8_t) ((u16) & 0x00ff)) @@ -137,12 +136,10 @@ //--------------------------------------------------------------------+ // INLINE FUNCTION //--------------------------------------------------------------------+ -#define memclr_(buffer, size) memset((buffer), 0, (size)) -#define varclr_(_var) memclr_(_var, sizeof(*(_var))) -#define arrclr_(_arr) memclr_(_arr, sizeof(_arr)) -#define arrcount_(_arr) ( sizeof(_arr) / sizeof(_arr[0]) ) +#define tu_memclr(buffer, size) memset((buffer), 0, (size)) +#define tu_varclr(_var) tu_memclr(_var, sizeof(*(_var))) -static inline bool mem_all_zero(void const* buffer, uint32_t size) +static inline bool tu_mem_test_zero (void const* buffer, uint32_t size) { uint8_t const* p_mem = (uint8_t const*) buffer; for(uint32_t i=0; i y) ? x : y; } -static inline uint16_t tu_max16(uint16_t x, uint16_t y) -{ - return (x > y) ? x : y; -} - //------------- Align -------------// static inline uint32_t tu_align32 (uint32_t value) { @@ -249,24 +241,6 @@ static inline uint8_t tu_log2(uint32_t value) return result; } -// return the number of set bits in value -static inline uint8_t tu_cardof(uint32_t value) -{ - // Brian Kernighan's method goes through as many iterations as there are set bits. So if we have a 32-bit word with only - // the high bit set, then it will only go once through the loop - // Published in 1988, the C Programming Language 2nd Ed. (by Brian W. Kernighan and Dennis M. Ritchie) - // mentions this in exercise 2-9. On April 19, 2006 Don Knuth pointed out to me that this method - // "was first published by Peter Wegner in CACM 3 (1960), 322. (Also discovered independently by Derrick Lehmer and - // published in 1964 in a book edited by Beckenbach.)" - uint8_t count; - for (count = 0; value; count++) - { - value &= value - 1; // clear the least significant bit set - } - - return count; -} - #ifdef __cplusplus } #endif diff --git a/src/device/usbd.c b/src/device/usbd.c index 89dd4b722..146f8ec89 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -274,7 +274,7 @@ static tusb_error_t usbd_main_st(void) tusb_error_t err; err = TUSB_ERROR_NONE; - memclr_(&event, sizeof(usbd_task_event_t)); + tu_memclr(&event, sizeof(usbd_task_event_t)); osal_queue_receive(_usbd_q, &event, OSAL_TIMEOUT_WAIT_FOREVER, &err); @@ -318,7 +318,7 @@ static tusb_error_t usbd_main_st(void) static void usbd_reset(uint8_t rhport) { - varclr_(&_usbd_dev); + tu_varclr(&_usbd_dev); memset(_usbd_dev.itf2drv, 0xff, sizeof(_usbd_dev.itf2drv)); // invalid mapping memset(_usbd_dev.ep2drv , 0xff, sizeof(_usbd_dev.ep2drv )); // invalid mapping diff --git a/src/host/ehci/ehci.c b/src/host/ehci/ehci.c index 84821e3f5..99e7fdb65 100644 --- a/src/host/ehci/ehci.c +++ b/src/host/ehci/ehci.c @@ -130,7 +130,7 @@ static tusb_error_t hcd_controller_stop(uint8_t hostid) ATTR_WARN_UNUSED_RESULT tusb_error_t hcd_init(void) { //------------- Data Structure init -------------// - memclr_(&ehci_data, sizeof(ehci_data_t)); + tu_memclr(&ehci_data, sizeof(ehci_data_t)); #if (CFG_TUSB_RHPORT0_MODE & OPT_MODE_HOST) TU_ASSERT_ERR (hcd_controller_init(0)); @@ -192,7 +192,7 @@ static tusb_error_t hcd_controller_init(uint8_t hostid) //------------- Asynchronous List -------------// ehci_qhd_t * const async_head = get_async_head(hostid); - memclr_(async_head, sizeof(ehci_qhd_t)); + tu_memclr(async_head, sizeof(ehci_qhd_t)); async_head->next.address = (uint32_t) async_head; // circular list, next is itself async_head->next.type = EHCI_QUEUE_ELEMENT_QHD; @@ -938,7 +938,7 @@ static void qhd_init(ehci_qhd_t *p_qhd, uint8_t dev_addr, uint16_t max_packet_si // address 0 is used as async head, which always on the list --> cannot be cleared (ehci halted otherwise) if (dev_addr != 0) { - memclr_(p_qhd, sizeof(ehci_qhd_t)); + tu_memclr(p_qhd, sizeof(ehci_qhd_t)); } p_qhd->device_address = dev_addr; @@ -1004,7 +1004,7 @@ static void qhd_init(ehci_qhd_t *p_qhd, uint8_t dev_addr, uint16_t max_packet_si static void qtd_init(ehci_qtd_t* p_qtd, uint32_t data_ptr, uint16_t total_bytes) { - memclr_(p_qtd, sizeof(ehci_qtd_t)); + tu_memclr(p_qtd, sizeof(ehci_qtd_t)); p_qtd->used = 1; diff --git a/src/host/hub.c b/src/host/hub.c index 063cef61a..624e43563 100644 --- a/src/host/hub.c +++ b/src/host/hub.c @@ -152,7 +152,7 @@ tusb_speed_t hub_port_get_speed(void) //--------------------------------------------------------------------+ void hub_init(void) { - memclr_(hub_data, CFG_TUSB_HOST_DEVICE_MAX*sizeof(usbh_hub_t)); + tu_memclr(hub_data, CFG_TUSB_HOST_DEVICE_MAX*sizeof(usbh_hub_t)); // hub_enum_sem_hdl = osal_semaphore_create( OSAL_SEM_REF(hub_enum_semaphore) ); } @@ -237,7 +237,7 @@ void hub_isr(pipe_handle_t pipe_hdl, tusb_event_t event, uint32_t xferred_bytes) void hub_close(uint8_t dev_addr) { (void) hcd_pipe_close(hub_data[dev_addr-1].pipe_status); - memclr_(&hub_data[dev_addr-1], sizeof(usbh_hub_t)); + tu_memclr(&hub_data[dev_addr-1], sizeof(usbh_hub_t)); // osal_semaphore_reset(hub_enum_sem_hdl); } diff --git a/src/host/ohci/ohci.c b/src/host/ohci/ohci.c index 1c9f3f293..b9183a025 100644 --- a/src/host/ohci/ohci.c +++ b/src/host/ohci/ohci.c @@ -164,7 +164,7 @@ static ohci_ed_t * ed_list_find_previous(ohci_ed_t const * p_head, ohci_ed_t con tusb_error_t hcd_init(void) { //------------- Data Structure init -------------// - memclr_(&ohci_data, sizeof(ohci_data_t)); + tu_memclr(&ohci_data, sizeof(ohci_data_t)); for(uint8_t i=0; i<32; i++) { // assign all interrupt pointes to period head ed ohci_data.hcca.interrupt_table[i] = (uint32_t) &ohci_data.period_head_ed; @@ -245,7 +245,7 @@ static void ed_init(ohci_ed_t *p_ed, uint8_t dev_addr, uint16_t max_packet_size, // address 0 is used as async head, which always on the list --> cannot be cleared if (dev_addr != 0) { - memclr_(p_ed, sizeof(ohci_ed_t)); + tu_memclr(p_ed, sizeof(ohci_ed_t)); } p_ed->device_address = dev_addr; @@ -261,7 +261,7 @@ static void ed_init(ohci_ed_t *p_ed, uint8_t dev_addr, uint16_t max_packet_size, static void gtd_init(ohci_gtd_t* p_td, void* data_ptr, uint16_t total_bytes) { - memclr_(p_td, sizeof(ohci_gtd_t)); + tu_memclr(p_td, sizeof(ohci_gtd_t)); p_td->used = 1; p_td->expected_bytes = total_bytes; diff --git a/src/host/usbh.c b/src/host/usbh.c index 8b858b2de..b849de9b9 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -142,7 +142,7 @@ uint32_t tuh_device_get_mounted_class_flag(uint8_t dev_addr) //--------------------------------------------------------------------+ tusb_error_t usbh_init(void) { - memclr_(usbh_devices, sizeof(usbh_device_info_t)*(CFG_TUSB_HOST_DEVICE_MAX+1)); + tu_memclr(usbh_devices, sizeof(usbh_device_info_t)*(CFG_TUSB_HOST_DEVICE_MAX+1)); TU_ASSERT_ERR( hcd_init() ); diff --git a/src/osal/osal_mynewt.h b/src/osal/osal_mynewt.h index db65ac553..59cd1b821 100644 --- a/src/osal/osal_mynewt.h +++ b/src/osal/osal_mynewt.h @@ -145,7 +145,7 @@ static inline bool osal_queue_send(osal_queue_t const queue_hdl, void const * da os_memblock_put(&queue_hdl->mpool, ptr); return false; } - memclr_(ev, sizeof(struct os_event)); + tu_memclr(ev, sizeof(struct os_event)); ev->ev_arg = ptr; os_eventq_put(&queue_hdl->evq, ev); diff --git a/src/portable/nordic/nrf5x/dcd_nrf5x.c b/src/portable/nordic/nrf5x/dcd_nrf5x.c index 01926c76e..371c291a3 100644 --- a/src/portable/nordic/nrf5x/dcd_nrf5x.c +++ b/src/portable/nordic/nrf5x/dcd_nrf5x.c @@ -108,7 +108,7 @@ void bus_reset(void) NRF_USBD->TASKS_STARTISOIN = 0; NRF_USBD->TASKS_STARTISOOUT = 0; - varclr_(&_dcd); + tu_varclr(&_dcd); } /*------------------------------------------------------------------*/ diff --git a/src/portable/nxp/lpc11xx_lpc13xx/dcd_lpc_11uxx_13uxx.c b/src/portable/nxp/lpc11xx_lpc13xx/dcd_lpc_11uxx_13uxx.c index 292d1fa6d..8e5a4d1aa 100644 --- a/src/portable/nxp/lpc11xx_lpc13xx/dcd_lpc_11uxx_13uxx.c +++ b/src/portable/nxp/lpc11xx_lpc13xx/dcd_lpc_11uxx_13uxx.c @@ -201,7 +201,7 @@ bool dcd_init(uint8_t rhport) static void bus_reset(void) { - memclr_(&dcd_data, sizeof(dcd_11u_13u_data_t)); + tu_memclr(&dcd_data, sizeof(dcd_11u_13u_data_t)); for(uint8_t ep_id = 2; ep_id < DCD_11U_13U_QHD_COUNT; ep_id++) { // disable all non-control endpoints on bus reset dcd_data.qhd[ep_id][0].disable = dcd_data.qhd[ep_id][1].disable = 1; @@ -473,7 +473,7 @@ edpt_hdl_t dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint TU_ASSERT( dcd_data.qhd[ep_id][0].disable && dcd_data.qhd[ep_id][1].disable, null_handle ); // endpoint must not previously opened, normally this means running out of endpoints - memclr_(dcd_data.qhd[ep_id], 2*sizeof(dcd_11u_13u_qhd_t)); + tu_memclr(dcd_data.qhd[ep_id], 2*sizeof(dcd_11u_13u_qhd_t)); dcd_data.qhd[ep_id][0].is_isochronous = dcd_data.qhd[ep_id][1].is_isochronous = (p_endpoint_desc->bmAttributes.xfer == TUSB_XFER_ISOCHRONOUS); dcd_data.class_code[ep_id] = class_code; diff --git a/src/portable/nxp/lpc17xx/dcd_lpc175x_6x.c b/src/portable/nxp/lpc17xx/dcd_lpc175x_6x.c index 4d3687830..189521d25 100644 --- a/src/portable/nxp/lpc17xx/dcd_lpc175x_6x.c +++ b/src/portable/nxp/lpc17xx/dcd_lpc175x_6x.c @@ -119,7 +119,7 @@ static void bus_reset(void) LPC_USB->USBNDDRIntClr = 0xFFFFFFFF; LPC_USB->USBSysErrIntClr = 0xFFFFFFFF; - memclr_(&dcd_data, sizeof(dcd_data_t)); + tu_memclr(&dcd_data, sizeof(dcd_data_t)); } bool dcd_init(uint8_t rhport) @@ -432,7 +432,7 @@ edpt_hdl_t dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint //------------- first DD prepare -------------// dcd_dma_descriptor_t* const p_dd = &dcd_data.dd[ep_id][0]; - memclr_(p_dd, sizeof(dcd_dma_descriptor_t)); + tu_memclr(p_dd, sizeof(dcd_dma_descriptor_t)); p_dd->is_isochronous = (p_endpoint_desc->bmAttributes.xfer == TUSB_XFER_ISOCHRONOUS) ? 1 : 0; p_dd->max_packet_size = p_endpoint_desc->wMaxPacketSize.size; @@ -498,7 +498,7 @@ tusb_error_t dcd_edpt_xfer(edpt_hdl_t edpt_hdl, uint8_t* buffer, uint16_t total_ { // setup new dd dcd_dma_descriptor_t* const p_dd = &dcd_data.dd[ edpt_hdl.index ][1]; - memclr_(p_dd, sizeof(dcd_dma_descriptor_t)); + tu_memclr(p_dd, sizeof(dcd_dma_descriptor_t)); dd_xfer_init(p_dd, buffer, total_bytes); diff --git a/src/portable/nxp/lpc43xx_lpc18xx/dcd_lpc43xx.c b/src/portable/nxp/lpc43xx_lpc18xx/dcd_lpc43xx.c index 7368542b8..5a7d61004 100644 --- a/src/portable/nxp/lpc43xx_lpc18xx/dcd_lpc43xx.c +++ b/src/portable/nxp/lpc43xx_lpc18xx/dcd_lpc43xx.c @@ -133,7 +133,7 @@ static void bus_reset(uint8_t rhport) //------------- Queue Head & Queue TD -------------// dcd_data_t* p_dcd = dcd_data_ptr[rhport]; - memclr_(p_dcd, sizeof(dcd_data_t)); + tu_memclr(p_dcd, sizeof(dcd_data_t)); //------------- Set up Control Endpoints (0 OUT, 1 IN) -------------// p_dcd->qhd[0].zero_length_termination = p_dcd->qhd[1].zero_length_termination = 1; @@ -149,7 +149,7 @@ bool dcd_init(uint8_t rhport) LPC_USB0_Type* const lpc_usb = LPC_USB[rhport]; dcd_data_t* p_dcd = dcd_data_ptr[rhport]; - memclr_(p_dcd, sizeof(dcd_data_t)); + tu_memclr(p_dcd, sizeof(dcd_data_t)); lpc_usb->ENDPOINTLISTADDR = (uint32_t) p_dcd->qhd; // Endpoint List Address has to be 2K alignment lpc_usb->USBSTS_D = lpc_usb->USBSTS_D; @@ -196,7 +196,7 @@ static inline uint8_t edpt_phy2log(uint8_t physical_endpoint) static void qtd_init(dcd_qtd_t* p_qtd, void * data_ptr, uint16_t total_bytes) { - memclr_(p_qtd, sizeof(dcd_qtd_t)); + tu_memclr(p_qtd, sizeof(dcd_qtd_t)); p_qtd->used = 1; @@ -303,7 +303,7 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc) uint8_t ep_idx = edpt_addr2phy(p_endpoint_desc->bEndpointAddress); dcd_qhd_t * p_qhd = &dcd_data_ptr[rhport]->qhd[ep_idx]; - memclr_(p_qhd, sizeof(dcd_qhd_t)); + tu_memclr(p_qhd, sizeof(dcd_qhd_t)); p_qhd->zero_length_termination = 1; p_qhd->max_package_size = p_endpoint_desc->wMaxPacketSize.size; diff --git a/tests/lpc175x_6x/test/test_dcd_lpc175x_6x.c b/tests/lpc175x_6x/test/test_dcd_lpc175x_6x.c index ef084fc77..31baa5f5c 100644 --- a/tests/lpc175x_6x/test/test_dcd_lpc175x_6x.c +++ b/tests/lpc175x_6x/test/test_dcd_lpc175x_6x.c @@ -51,9 +51,9 @@ extern dcd_dma_descriptor_t dcd_dd[DCD_MAX_DD]; void setUp(void) { - memclr_(dcd_udca, 32*4); - memclr_(dcd_dd, sizeof(dcd_dma_descriptor_t)*DCD_MAX_DD); - memclr_(&lpc_usb, sizeof(LPC_USB_TypeDef)); + tu_memclr(dcd_udca, 32*4); + tu_memclr(dcd_dd, sizeof(dcd_dma_descriptor_t)*DCD_MAX_DD); + tu_memclr(&lpc_usb, sizeof(LPC_USB_TypeDef)); } void tearDown(void) @@ -129,7 +129,7 @@ void test_dcd_configure_endpoint_in(void) }; dcd_init(); - memclr_(&lpc_usb, sizeof(LPC_USB_TypeDef)); // clear to examine register after CUT + tu_memclr(&lpc_usb, sizeof(LPC_USB_TypeDef)); // clear to examine register after CUT //------------- Code Under Test -------------// dcd_pipe_open(0, &desc_endpoint); diff --git a/tests/lpc18xx_43xx/test/host/cdc/test_cdc_host.c b/tests/lpc18xx_43xx/test/host/cdc/test_cdc_host.c index a74270e8b..5077eea93 100644 --- a/tests/lpc18xx_43xx/test/host/cdc/test_cdc_host.c +++ b/tests/lpc18xx_43xx/test/host/cdc/test_cdc_host.c @@ -71,7 +71,7 @@ void setUp(void) length = 0; dev_addr = 1; - memclr_(cdch_data, sizeof(cdch_data_t)*CFG_TUSB_HOST_DEVICE_MAX); + tu_memclr(cdch_data, sizeof(cdch_data_t)*CFG_TUSB_HOST_DEVICE_MAX); } void tearDown(void) diff --git a/tests/lpc18xx_43xx/test/host/ehci/test_pipe_bulk_open.c b/tests/lpc18xx_43xx/test/host/ehci/test_pipe_bulk_open.c index a26b990d3..581488d7d 100644 --- a/tests/lpc18xx_43xx/test/host/ehci/test_pipe_bulk_open.c +++ b/tests/lpc18xx_43xx/test/host/ehci/test_pipe_bulk_open.c @@ -70,7 +70,7 @@ void setUp(void) dev_addr = 1; hostid = RANDOM(CONTROLLER_HOST_NUMBER) + TEST_CONTROLLER_HOST_START_INDEX; - memclr_(usbh_devices, sizeof(usbh_device_info_t)*(CFG_TUSB_HOST_DEVICE_MAX+1)); + tu_memclr(usbh_devices, sizeof(usbh_device_info_t)*(CFG_TUSB_HOST_DEVICE_MAX+1)); helper_usbh_device_emulate(dev_addr, hub_addr, hub_port, hostid, TUSB_SPEED_HIGH); async_head = get_async_head( hostid ); diff --git a/tests/lpc18xx_43xx/test/host/ehci/test_pipe_bulk_xfer.c b/tests/lpc18xx_43xx/test/host/ehci/test_pipe_bulk_xfer.c index a52c721fe..2e9e29fdc 100644 --- a/tests/lpc18xx_43xx/test/host/ehci/test_pipe_bulk_xfer.c +++ b/tests/lpc18xx_43xx/test/host/ehci/test_pipe_bulk_xfer.c @@ -90,8 +90,8 @@ tusb_desc_endpoint_t const desc_ept_bulk_out = void setUp(void) { ehci_controller_init(); - memclr_(xfer_data, sizeof(xfer_data)); - memclr_(usbh_devices, sizeof(usbh_device_info_t)*(CFG_TUSB_HOST_DEVICE_MAX+1)); + tu_memclr(xfer_data, sizeof(xfer_data)); + tu_memclr(usbh_devices, sizeof(usbh_device_info_t)*(CFG_TUSB_HOST_DEVICE_MAX+1)); TEST_ASSERT_STATUS( hcd_init() ); diff --git a/tests/lpc18xx_43xx/test/host/ehci/test_pipe_control_open.c b/tests/lpc18xx_43xx/test/host/ehci/test_pipe_control_open.c index 22cbf7569..426fed9f2 100644 --- a/tests/lpc18xx_43xx/test/host/ehci/test_pipe_control_open.c +++ b/tests/lpc18xx_43xx/test/host/ehci/test_pipe_control_open.c @@ -67,7 +67,7 @@ static ehci_qhd_t *p_control_qhd; //--------------------------------------------------------------------+ void setUp(void) { - memclr_(usbh_devices, sizeof(usbh_device_info_t)*(CFG_TUSB_HOST_DEVICE_MAX+1)); + tu_memclr(usbh_devices, sizeof(usbh_device_info_t)*(CFG_TUSB_HOST_DEVICE_MAX+1)); TEST_ASSERT_STATUS( hcd_init() ); diff --git a/tests/lpc18xx_43xx/test/host/ehci/test_pipe_control_xfer.c b/tests/lpc18xx_43xx/test/host/ehci/test_pipe_control_xfer.c index 286aae113..ffd7ffb67 100644 --- a/tests/lpc18xx_43xx/test/host/ehci/test_pipe_control_xfer.c +++ b/tests/lpc18xx_43xx/test/host/ehci/test_pipe_control_xfer.c @@ -74,8 +74,8 @@ void setUp(void) { ehci_controller_init(); - memclr_(usbh_devices, sizeof(usbh_device_info_t)*(CFG_TUSB_HOST_DEVICE_MAX+1)); - memclr_(xfer_data, sizeof(xfer_data)); + tu_memclr(usbh_devices, sizeof(usbh_device_info_t)*(CFG_TUSB_HOST_DEVICE_MAX+1)); + tu_memclr(xfer_data, sizeof(xfer_data)); TEST_ASSERT_STATUS( hcd_init() ); diff --git a/tests/lpc18xx_43xx/test/host/ehci/test_pipe_interrupt_open.c b/tests/lpc18xx_43xx/test/host/ehci/test_pipe_interrupt_open.c index f39021ef2..b243a468e 100644 --- a/tests/lpc18xx_43xx/test/host/ehci/test_pipe_interrupt_open.c +++ b/tests/lpc18xx_43xx/test/host/ehci/test_pipe_interrupt_open.c @@ -67,7 +67,7 @@ static pipe_handle_t pipe_hdl; //--------------------------------------------------------------------+ void setUp(void) { - memclr_(usbh_devices, sizeof(usbh_device_info_t)*(CFG_TUSB_HOST_DEVICE_MAX+1)); + tu_memclr(usbh_devices, sizeof(usbh_device_info_t)*(CFG_TUSB_HOST_DEVICE_MAX+1)); hcd_init(); @@ -78,7 +78,7 @@ void setUp(void) period_head_arr = get_period_head( hostid, 1 ); p_int_qhd = NULL; - memclr_(&pipe_hdl, sizeof(pipe_handle_t)); + tu_memclr(&pipe_hdl, sizeof(pipe_handle_t)); } void tearDown(void) diff --git a/tests/lpc18xx_43xx/test/host/ehci/test_pipe_interrupt_xfer.c b/tests/lpc18xx_43xx/test/host/ehci/test_pipe_interrupt_xfer.c index aeb094932..827db2897 100644 --- a/tests/lpc18xx_43xx/test/host/ehci/test_pipe_interrupt_xfer.c +++ b/tests/lpc18xx_43xx/test/host/ehci/test_pipe_interrupt_xfer.c @@ -91,8 +91,8 @@ void setUp(void) { ehci_controller_init(); - memclr_(usbh_devices, sizeof(usbh_device_info_t)*(CFG_TUSB_HOST_DEVICE_MAX+1)); - memclr_(xfer_data, sizeof(xfer_data)); + tu_memclr(usbh_devices, sizeof(usbh_device_info_t)*(CFG_TUSB_HOST_DEVICE_MAX+1)); + tu_memclr(xfer_data, sizeof(xfer_data)); TEST_ASSERT_STATUS( hcd_init() ); diff --git a/tests/lpc18xx_43xx/test/host/ehci/test_pipe_isochronous_open.c b/tests/lpc18xx_43xx/test/host/ehci/test_pipe_isochronous_open.c index 584c44471..1feff94e5 100644 --- a/tests/lpc18xx_43xx/test/host/ehci/test_pipe_isochronous_open.c +++ b/tests/lpc18xx_43xx/test/host/ehci/test_pipe_isochronous_open.c @@ -63,7 +63,7 @@ static ehci_qhd_t *period_head_arr; //--------------------------------------------------------------------+ void setUp(void) { - memclr_(usbh_devices, sizeof(usbh_device_info_t)*(CFG_TUSB_HOST_DEVICE_MAX+1)); + tu_memclr(usbh_devices, sizeof(usbh_device_info_t)*(CFG_TUSB_HOST_DEVICE_MAX+1)); hcd_init(); diff --git a/tests/lpc18xx_43xx/test/host/hid/test_hidh_keyboard.c b/tests/lpc18xx_43xx/test/host/hid/test_hidh_keyboard.c index 75c8f8a90..b3b49c172 100644 --- a/tests/lpc18xx_43xx/test/host/hid/test_hidh_keyboard.c +++ b/tests/lpc18xx_43xx/test/host/hid/test_hidh_keyboard.c @@ -73,7 +73,7 @@ tusb_desc_endpoint_t const *p_kdb_endpoint_desc = &desc_configuration.keyboard void setUp(void) { hidh_init(); - memclr_(&report, sizeof(hid_keyboard_report_t)); + tu_memclr(&report, sizeof(hid_keyboard_report_t)); dev_addr = RANDOM(CFG_TUSB_HOST_DEVICE_MAX)+1; p_hidh_kbd = &keyboardh_data[dev_addr-1]; diff --git a/tests/lpc18xx_43xx/test/host/hid/test_hidh_mouse.c b/tests/lpc18xx_43xx/test/host/hid/test_hidh_mouse.c index 741f54428..b1a3558e6 100644 --- a/tests/lpc18xx_43xx/test/host/hid/test_hidh_mouse.c +++ b/tests/lpc18xx_43xx/test/host/hid/test_hidh_mouse.c @@ -62,7 +62,7 @@ void setUp(void) { hidh_init(); - memclr_(&report, sizeof(hid_mouse_report_t)); + tu_memclr(&report, sizeof(hid_mouse_report_t)); dev_addr = RANDOM(CFG_TUSB_HOST_DEVICE_MAX)+1; p_hidh_mouse = &mouseh_data[dev_addr-1]; diff --git a/tests/lpc18xx_43xx/test/host/usbh/test_enum_task.c b/tests/lpc18xx_43xx/test/host/usbh/test_enum_task.c index 7aeba21a0..a85c3c48a 100644 --- a/tests/lpc18xx_43xx/test/host/usbh/test_enum_task.c +++ b/tests/lpc18xx_43xx/test/host/usbh/test_enum_task.c @@ -73,7 +73,7 @@ enum { void setUp(void) { - memclr_(usbh_devices, sizeof(usbh_device_info_t)*(CFG_TUSB_HOST_DEVICE_MAX+1)); + tu_memclr(usbh_devices, sizeof(usbh_device_info_t)*(CFG_TUSB_HOST_DEVICE_MAX+1)); osal_queue_receive_StubWithCallback(queue_recv_stub); osal_semaphore_wait_StubWithCallback(semaphore_wait_success_stub); diff --git a/tests/support/ehci_controller_fake.c b/tests/support/ehci_controller_fake.c index 041e1dbb5..acd40cc0b 100644 --- a/tests/support/ehci_controller_fake.c +++ b/tests/support/ehci_controller_fake.c @@ -61,8 +61,8 @@ extern usbh_device_info_t usbh_devices[CFG_TUSB_HOST_DEVICE_MAX+1]; //--------------------------------------------------------------------+ void ehci_controller_init(void) { - memclr_(&lpc_usb0, sizeof(LPC_USB0_Type)); - memclr_(&lpc_usb1, sizeof(LPC_USB1_Type)); + tu_memclr(&lpc_usb0, sizeof(LPC_USB0_Type)); + tu_memclr(&lpc_usb1, sizeof(LPC_USB1_Type)); } void ehci_controller_control_xfer_proceed(uint8_t dev_addr, uint8_t p_data[]) diff --git a/tests/support/type_helper.h b/tests/support/type_helper.h index 3e27cef2e..36502ba35 100644 --- a/tests/support/type_helper.h +++ b/tests/support/type_helper.h @@ -75,7 +75,7 @@ ({\ uint32_t value=0;\ struct_type str;\ - memclr_((void*)&str, sizeof(struct_type));\ + tu_memclr((void*)&str, sizeof(struct_type));\ str.member.bitfield_member = 1;\ memcpy(&value, (void*)&str.member, sizeof(str.member));\ tu_log2( value );\ @@ -84,7 +84,7 @@ #define BITFIELD_OFFSET_OF_UINT32(struct_type, offset, bitfield_member) \ ({\ struct_type str;\ - memclr_(&str, sizeof(struct_type));\ + tu_memclr(&str, sizeof(struct_type));\ str.bitfield_member = 1;\ tu_log2( ((uint32_t*) &str)[offset] );\ }) -- cgit v1.3.1 From 55427606ef7fbdafa5a9da6b8a0f798dcb619817 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 24 Oct 2018 00:44:26 +0700 Subject: replace dcd_xfer_complete by dcd_xfer_complete() --- src/class/msc/msc_device.c | 8 ++--- src/common/tusb_types.h | 3 -- src/device/dcd.h | 26 +++++++++++---- src/device/usbd.c | 46 ++++++++++---------------- src/portable/nordic/nrf5x/dcd_nrf5x.c | 16 ++++----- src/portable/nxp/lpc43xx_lpc18xx/dcd_lpc43xx.c | 22 ++++++------ 6 files changed, 59 insertions(+), 62 deletions(-) (limited to 'src/common') diff --git a/src/class/msc/msc_device.c b/src/class/msc/msc_device.c index 4d2f9249c..b050ea705 100644 --- a/src/class/msc/msc_device.c +++ b/src/class/msc/msc_device.c @@ -304,7 +304,7 @@ tusb_error_t mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, tusb_event_t event, u // Complete IN while waiting for CMD is usually Status of previous SCSI op, ignore it if(ep_addr != p_msc->ep_out) return TUSB_ERROR_NONE; - TU_ASSERT( event == TUSB_EVENT_XFER_COMPLETE && + TU_ASSERT( event == DCD_XFER_SUCCESS && xferred_bytes == sizeof(msc_cbw_t) && p_cbw->signature == MSC_CBW_SIGNATURE, TUSB_ERROR_INVALID_PARA ); p_csw->signature = MSC_CSW_SIGNATURE; @@ -434,7 +434,7 @@ tusb_error_t mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, tusb_event_t event, u } // simulate an transfer complete with adjusted parameters --> this driver callback will fired again - dcd_xfer_complete(rhport, p_msc->ep_out, xferred_bytes-nbytes, true); + dcd_event_xfer_complete(rhport, p_msc->ep_out, xferred_bytes-nbytes, DCD_XFER_SUCCESS, false); return TUSB_ERROR_NONE; // skip the rest } @@ -483,7 +483,7 @@ tusb_error_t mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, tusb_event_t event, u if ( dcd_edpt_stalled(rhport, p_msc->ep_in) || dcd_edpt_stalled(rhport, p_msc->ep_out) ) { // simulate an transfer complete with adjusted parameters --> this driver callback will fired again - dcd_xfer_complete(rhport, p_msc->ep_out, 0, true); + dcd_event_xfer_complete(rhport, p_msc->ep_out, 0, DCD_XFER_SUCCESS, false); } else { @@ -545,7 +545,7 @@ static void proc_read10_cmd(uint8_t rhport, mscd_interface_t* p_msc) else if ( nbytes == 0 ) { // zero means not ready -> simulate an transfer complete so that this driver callback will fired again - dcd_xfer_complete(rhport, p_msc->ep_in, 0, true); + dcd_event_xfer_complete(rhport, p_msc->ep_in, 0, DCD_XFER_SUCCESS, false); } else { diff --git a/src/common/tusb_types.h b/src/common/tusb_types.h index ee9e849bf..8ce334e55 100644 --- a/src/common/tusb_types.h +++ b/src/common/tusb_types.h @@ -197,9 +197,6 @@ typedef enum TUSB_EVENT_XFER_COMPLETE, TUSB_EVENT_XFER_ERROR, TUSB_EVENT_XFER_STALLED, - - TUSB_EVENT_BUS_RESET, // TODO refractor - TUSB_EVENT_SETUP_RECEIVED, }tusb_event_t; enum { diff --git a/src/device/dcd.h b/src/device/dcd.h index 5a28296cd..662496701 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -49,6 +49,13 @@ extern "C" { #endif +enum +{ + DCD_XFER_SUCCESS = 0, + DCD_XFER_FAILED, + DCD_XFER_STALLED +}; + typedef enum { DCD_EVENT_BUS_RESET = 1, @@ -103,15 +110,22 @@ void dcd_disconnect (uint8_t rhport) ATTR_WEAK; /* Event Function * Called by DCD to notify USBD *------------------------------------------------------------------*/ -void dcd_xfer_complete (uint8_t rhport, uint8_t ep_addr, uint32_t xferred_bytes, bool succeeded); +void dcd_event_handler(dcd_event_t const * event, bool in_isr); -static inline void dcd_control_complete(uint8_t rhport, uint32_t xferred_bytes) +static inline void dcd_event_xfer_complete(uint8_t rhport, uint8_t ep_addr, uint32_t xferred_bytes, uint8_t result, bool in_isr) { - // all control complete is successful !! - dcd_xfer_complete(rhport, 0, xferred_bytes, true); -} + dcd_event_t event = + { + .rhport = 0, + .event_id = DCD_EVENT_XFER_COMPLETE, + }; -void dcd_event_handler(dcd_event_t const * event, bool in_isr); + event.xfer_complete.ep_addr = ep_addr; + event.xfer_complete.len = xferred_bytes; + event.xfer_complete.result = result; + + dcd_event_handler(&event, true); +} /*------------------------------------------------------------------*/ /* Endpoint API diff --git a/src/device/usbd.c b/src/device/usbd.c index 58581d609..f35671f17 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -164,7 +164,7 @@ static osal_queue_t _usbd_q; /*------------- control transfer semaphore -------------*/ static osal_semaphore_def_t _usbd_sem_def; -/*static*/ osal_semaphore_t _usbd_ctrl_sem; +osal_semaphore_t _usbd_ctrl_sem; //--------------------------------------------------------------------+ // INTERNAL FUNCTION @@ -532,34 +532,6 @@ static void mark_interface_endpoint(uint8_t const* p_desc, uint16_t desc_len, ui //--------------------------------------------------------------------+ // USBD-DCD Callback API //--------------------------------------------------------------------+ -void dcd_xfer_complete(uint8_t rhport, uint8_t ep_addr, uint32_t xferred_bytes, bool succeeded) -{ - if (ep_addr == 0 ) - { - // Control Transfer - (void) rhport; - (void) succeeded; - - // only signal data stage, skip status (zero byte) - if (xferred_bytes) osal_semaphore_post( _usbd_ctrl_sem, true); - }else - { - dcd_event_t event = - { - .rhport = rhport, - .event_id = DCD_EVENT_XFER_COMPLETE, - }; - - event.xfer_complete.ep_addr = ep_addr; - event.xfer_complete.len = xferred_bytes; - event.xfer_complete.result = succeeded ? TUSB_EVENT_XFER_COMPLETE : TUSB_EVENT_XFER_ERROR; - - osal_queue_send(_usbd_q, &event, true); - } - - TU_ASSERT(succeeded, ); -} - void dcd_event_handler(dcd_event_t const * event, bool in_isr) { uint8_t const rhport = event->rhport; @@ -603,6 +575,22 @@ void dcd_event_handler(dcd_event_t const * event, bool in_isr) osal_queue_send(_usbd_q, event, in_isr); break; + case DCD_EVENT_XFER_COMPLETE: + if (event->xfer_complete.ep_addr == 0) + { + // only signal data stage, skip status (zero byte) + if (event->xfer_complete.len) + { + (void) event->xfer_complete.result; // TODO handle control error/stalled + osal_semaphore_post( _usbd_ctrl_sem, true); + } + }else + { + osal_queue_send(_usbd_q, event, true); + } + TU_ASSERT(event->xfer_complete.result == DCD_XFER_SUCCESS,); + break; + default: break; } } diff --git a/src/portable/nordic/nrf5x/dcd_nrf5x.c b/src/portable/nordic/nrf5x/dcd_nrf5x.c index f04acb6e3..d1ca91173 100644 --- a/src/portable/nordic/nrf5x/dcd_nrf5x.c +++ b/src/portable/nordic/nrf5x/dcd_nrf5x.c @@ -414,14 +414,12 @@ void USBD_IRQHandler(void) } } - dcd_event_t event = { .rhport = 0 }; - /*------------- Interrupt Processing -------------*/ if ( int_status & USBD_INTEN_USBRESET_Msk ) { bus_reset(); - event.event_id = DCD_EVENT_BUS_RESET; + dcd_event_t event = { .rhport = 0, .event_id = DCD_EVENT_BUS_RESET }; dcd_event_handler(&event, true); } @@ -439,7 +437,7 @@ void USBD_IRQHandler(void) NRF_USBD->WINDEXL , NRF_USBD->WINDEXH , NRF_USBD->WLENGTHL, NRF_USBD->WLENGTHH }; - event.event_id = DCD_EVENT_SETUP_RECEIVED; + dcd_event_t event = { .rhport = 0, .event_id = DCD_EVENT_SETUP_RECEIVED }; memcpy(&event.setup_received, setup, 8); dcd_event_handler(&event, true); @@ -461,7 +459,7 @@ void USBD_IRQHandler(void) }else { // Control IN complete - dcd_control_complete(0, _dcd.control.actual_len); + dcd_event_xfer_complete(0, 0, _dcd.control.actual_len, DCD_XFER_SUCCESS, true); } } } @@ -475,7 +473,7 @@ void USBD_IRQHandler(void) }else { // Control OUT complete - dcd_control_complete(0, _dcd.control.actual_len); + dcd_event_xfer_complete(0, 0, _dcd.control.actual_len, DCD_XFER_SUCCESS, true); } } @@ -506,7 +504,7 @@ void USBD_IRQHandler(void) xfer->total_len = xfer->actual_len; // BULK/INT OUT complete - dcd_xfer_complete(0, epnum, xfer->actual_len, true); + dcd_event_xfer_complete(0, epnum, xfer->actual_len, DCD_XFER_SUCCESS, true); } } @@ -535,7 +533,7 @@ void USBD_IRQHandler(void) } else { // Bulk/Int IN complete - dcd_xfer_complete(0, epnum | TUSB_DIR_IN_MASK, xfer->actual_len, true); + dcd_event_xfer_complete(0, epnum | TUSB_DIR_IN_MASK, xfer->actual_len, DCD_XFER_SUCCESS, true); } } } @@ -563,7 +561,7 @@ void USBD_IRQHandler(void) // SOF interrupt if ( int_status & USBD_INTEN_SOF_Msk ) { - event.event_id = DCD_EVENT_SOF; + dcd_event_t event = { .rhport = 0, .event_id = DCD_EVENT_SOF }; dcd_event_handler(&event, true); } } diff --git a/src/portable/nxp/lpc43xx_lpc18xx/dcd_lpc43xx.c b/src/portable/nxp/lpc43xx_lpc18xx/dcd_lpc43xx.c index 6e1d96168..8d53759e6 100644 --- a/src/portable/nxp/lpc43xx_lpc18xx/dcd_lpc43xx.c +++ b/src/portable/nxp/lpc43xx_lpc18xx/dcd_lpc43xx.c @@ -398,10 +398,11 @@ void xfer_complete_isr(uint8_t rhport, uint32_t reg_complete) if (p_qtd->int_on_complete) { - bool succeeded = ( p_qtd->xact_err || p_qtd->halted || p_qtd->buffer_err ) ? false : true; + uint8_t result = p_qtd->halted ? DCD_XFER_STALLED : + ( p_qtd->xact_err ||p_qtd->buffer_err ) ? DCD_XFER_FAILED : DCD_XFER_SUCCESS; uint8_t ep_addr = edpt_phy2addr(ep_idx); - dcd_xfer_complete(rhport, ep_addr, p_qtd->expected_bytes - p_qtd->total_bytes, succeeded); // only number of bytes in the IOC qtd + dcd_event_xfer_complete(rhport, ep_addr, p_qtd->expected_bytes - p_qtd->total_bytes, result, true); // only number of bytes in the IOC qtd } } } @@ -418,13 +419,12 @@ void hal_dcd_isr(uint8_t rhport) if (int_status == 0) return;// disabled interrupt sources - dcd_event_t event = { .rhport = rhport }; if (int_status & INT_MASK_RESET) { bus_reset(rhport); - event.event_id = DCD_EVENT_BUS_RESET; + dcd_event_t event = { .rhport = rhport, .event_id = DCD_EVENT_BUS_RESET }; dcd_event_handler(&event, true); } @@ -434,7 +434,7 @@ void hal_dcd_isr(uint8_t rhport) { // Note: Host may delay more than 3 ms before and/or after bus reset before doing enumeration. if ((lpc_usb->DEVICEADDR >> 25) & 0x0f) { - event.event_id = DCD_EVENT_SUSPENDED; + dcd_event_t event = { .rhport = rhport, .event_id = DCD_EVENT_SUSPENDED }; dcd_event_handler(&event, true); } } @@ -445,7 +445,7 @@ void hal_dcd_isr(uint8_t rhport) // { // if ( !(lpc_usb->PORTSC1_D & PORTSC_CURRENT_CONNECT_STATUS_MASK) ) // { -// event.event_id = DCD_EVENT_UNPLUGGED; +// dcd_event_t event = { .rhport = rhport, .event_id = DCD_EVENT_UNPLUGGED }; // dcd_event_handler(&event, true); // } // } @@ -463,7 +463,7 @@ void hal_dcd_isr(uint8_t rhport) // 23.10.10.2 Operational model for setup transfers lpc_usb->ENDPTSETUPSTAT = lpc_usb->ENDPTSETUPSTAT;// acknowledge - event.event_id = DCD_EVENT_SETUP_RECEIVED; + dcd_event_t event = { .rhport = rhport, .event_id = DCD_EVENT_SETUP_RECEIVED }; event.setup_received = p_dcd->qhd[0].setup_request; dcd_event_handler(&event, true); @@ -480,10 +480,10 @@ void hal_dcd_isr(uint8_t rhport) if ( p_qtd->int_on_complete ) { - bool succeeded = ( p_qtd->xact_err || p_qtd->halted || p_qtd->buffer_err ) ? false : true; - (void) succeeded; + uint8_t result = p_qtd->halted ? DCD_XFER_STALLED : + ( p_qtd->xact_err ||p_qtd->buffer_err ) ? DCD_XFER_FAILED : DCD_XFER_SUCCESS; - dcd_control_complete(rhport, p_qtd->expected_bytes - p_qtd->total_bytes); + dcd_event_xfer_complete(rhport, 0, p_qtd->expected_bytes - p_qtd->total_bytes, result, true); } } @@ -496,7 +496,7 @@ void hal_dcd_isr(uint8_t rhport) if (int_status & INT_MASK_SOF) { - event.event_id = DCD_EVENT_SOF; + dcd_event_t event = { .rhport = rhport, .event_id = DCD_EVENT_SOF }; dcd_event_handler(&event, true); } -- cgit v1.3.1 From bfa10016ae353779f7b94da31156ac997062322a Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 24 Oct 2018 12:37:43 +0700 Subject: rename verify_breakpoint to TU_BREAKPOINT --- src/class/msc/msc_device.c | 2 +- src/common/tusb_verify.h | 16 ++++++++-------- src/device/usbd.c | 2 +- src/host/ehci/ehci.c | 2 +- src/osal/osal_none.h | 8 ++++---- 5 files changed, 15 insertions(+), 15 deletions(-) (limited to 'src/common') diff --git a/src/class/msc/msc_device.c b/src/class/msc/msc_device.c index b050ea705..5a047b016 100644 --- a/src/class/msc/msc_device.c +++ b/src/class/msc/msc_device.c @@ -468,7 +468,7 @@ tusb_error_t mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, tusb_event_t event, u }else { // No other command take more than one transfer yet -> unlikely error - verify_breakpoint(); + TU_BREAKPOINT(); } } break; diff --git a/src/common/tusb_verify.h b/src/common/tusb_verify.h index 41c2b5be1..1cb8443bc 100644 --- a/src/common/tusb_verify.h +++ b/src/common/tusb_verify.h @@ -74,14 +74,14 @@ // Halt CPU (breakpoint) when hitting error, only apply for Cortex M3, M4, M7 #if defined(__ARM_ARCH_7M__) || defined (__ARM_ARCH_7EM__) -#define verify_breakpoint() \ +#define TU_BREAKPOINT() \ do {\ volatile uint32_t* ARM_CM_DHCSR = ((volatile uint32_t*) 0xE000EDF0UL); /* Cortex M CoreDebug->DHCSR */ \ if ( (*ARM_CM_DHCSR) & 1UL ) __asm("BKPT #0\n"); /* Only halt mcu if debugger is attached */\ } while(0) #else -#define verify_breakpoint() +#define TU_BREAKPOINT() #endif /*------------------------------------------------------------------*/ @@ -157,21 +157,21 @@ /*------------------------------------------------------------------*/ /* ASSERT - * basically TU_VERIFY with verify_breakpoint() as handler + * basically TU_VERIFY with TU_BREAKPOINT() as handler * - 1 arg : return false if failed * - 2 arg : return error if failed *------------------------------------------------------------------*/ -#define ASSERT_1ARGS(_cond) TU_VERIFY_DEFINE(_cond, _MESS_FAILED(); verify_breakpoint(), false) -#define ASSERT_2ARGS(_cond, _ret) TU_VERIFY_DEFINE(_cond, _MESS_FAILED(); verify_breakpoint(), _ret) +#define ASSERT_1ARGS(_cond) TU_VERIFY_DEFINE(_cond, _MESS_FAILED(); TU_BREAKPOINT(), false) +#define ASSERT_2ARGS(_cond, _ret) TU_VERIFY_DEFINE(_cond, _MESS_FAILED(); TU_BREAKPOINT(), _ret) #define TU_ASSERT(...) GET_3RD_ARG(__VA_ARGS__, ASSERT_2ARGS, ASSERT_1ARGS)(__VA_ARGS__) /*------------------------------------------------------------------*/ /* ASSERT Error - * basically TU_VERIFY Error with verify_breakpoint() as handler + * basically TU_VERIFY Error with TU_BREAKPOINT() as handler *------------------------------------------------------------------*/ -#define ASERT_ERR_1ARGS(_error) TU_VERIFY_ERR_DEF2(_error, verify_breakpoint()) -#define ASERT_ERR_2ARGS(_error, _ret) TU_VERIFY_ERR_DEF3(_error, verify_breakpoint(), _ret) +#define ASERT_ERR_1ARGS(_error) TU_VERIFY_ERR_DEF2(_error, TU_BREAKPOINT()) +#define ASERT_ERR_2ARGS(_error, _ret) TU_VERIFY_ERR_DEF3(_error, TU_BREAKPOINT(), _ret) #define TU_ASSERT_ERR(...) GET_3RD_ARG(__VA_ARGS__, ASERT_ERR_2ARGS, ASERT_ERR_1ARGS)(__VA_ARGS__) diff --git a/src/device/usbd.c b/src/device/usbd.c index f35671f17..1e96983b1 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -274,7 +274,7 @@ static tusb_error_t usbd_main_st(void) } else { - verify_breakpoint(); + TU_BREAKPOINT(); } } diff --git a/src/host/ehci/ehci.c b/src/host/ehci/ehci.c index 99e7fdb65..c7ff70d70 100644 --- a/src/host/ehci/ehci.c +++ b/src/host/ehci/ehci.c @@ -646,7 +646,7 @@ static void qhd_xfer_error_isr(ehci_qhd_t * p_qhd) p_qhd->total_xferred_bytes += p_qhd->p_qtd_list_head->expected_bytes - p_qhd->p_qtd_list_head->total_bytes; -// if ( TUSB_EVENT_XFER_ERROR == error_event ) verify_breakpoint(); // TODO skip unplugged device +// if ( TUSB_EVENT_XFER_ERROR == error_event ) TU_BREAKPOINT(); // TODO skip unplugged device p_qhd->p_qtd_list_head->used = 0; // free QTD qtd_remove_1st_from_qhd(p_qhd); diff --git a/src/osal/osal_none.h b/src/osal/osal_none.h index 91848f221..783e4fd2e 100644 --- a/src/osal/osal_none.h +++ b/src/osal/osal_none.h @@ -113,11 +113,11 @@ static inline bool osal_task_create(osal_task_def_t* taskdef) //------------- Sub Task Assert -------------// #define STASK_RETURN(error) do { TASK_RESTART; return error; } while(0) -#define STASK_ASSERT_ERR(_err) TU_VERIFY_ERR_HDLR(_err, verify_breakpoint(); TASK_RESTART, TUSB_ERROR_FAILED) -#define STASK_ASSERT_ERR_HDLR(_err, _func) TU_VERIFY_ERR_HDLR(_err, verify_breakpoint(); _func; TASK_RESTART, TUSB_ERROR_FAILED ) +#define STASK_ASSERT_ERR(_err) TU_VERIFY_ERR_HDLR(_err, TU_BREAKPOINT(); TASK_RESTART, TUSB_ERROR_FAILED) +#define STASK_ASSERT_ERR_HDLR(_err, _func) TU_VERIFY_ERR_HDLR(_err, TU_BREAKPOINT(); _func; TASK_RESTART, TUSB_ERROR_FAILED ) -#define STASK_ASSERT(_cond) TU_VERIFY_HDLR(_cond, verify_breakpoint(); TASK_RESTART, TUSB_ERROR_FAILED) -#define STASK_ASSERT_HDLR(_cond, _func) TU_VERIFY_HDLR(_cond, verify_breakpoint(); _func; TASK_RESTART, TUSB_ERROR_FAILED) +#define STASK_ASSERT(_cond) TU_VERIFY_HDLR(_cond, TU_BREAKPOINT(); TASK_RESTART, TUSB_ERROR_FAILED) +#define STASK_ASSERT_HDLR(_cond, _func) TU_VERIFY_HDLR(_cond, TU_BREAKPOINT(); _func; TASK_RESTART, TUSB_ERROR_FAILED) //--------------------------------------------------------------------+ // QUEUE API -- cgit v1.3.1 From f6076b0e0621b13f8d76f51dc703024347af00f3 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 2 Nov 2018 17:28:07 +0700 Subject: add mutex support (optional) for tu_fifo --- src/common/tusb_common.h | 1 - src/common/tusb_fifo.c | 70 +++++++++++++++++++++++++++++++++--------------- src/common/tusb_fifo.h | 58 +++++++++++++-------------------------- 3 files changed, 67 insertions(+), 62 deletions(-) (limited to 'src/common') diff --git a/src/common/tusb_common.h b/src/common/tusb_common.h index 85bd15d43..3c5402e59 100644 --- a/src/common/tusb_common.h +++ b/src/common/tusb_common.h @@ -66,7 +66,6 @@ #include "tusb_verify.h" #include "binary.h" #include "tusb_error.h" -#include "tusb_fifo.h" #include "tusb_timeout.h" #include "tusb_types.h" diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index 818f4e9cb..e0b3d0aa0 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -36,24 +36,51 @@ */ /**************************************************************************/ +#include + +#include "osal/osal.h" #include "tusb_fifo.h" -#include "common/tusb_verify.h" // for ASSERT +// implement mutex lock and unlock +// For OSAL_NONE: if mutex is locked by other, function return immediately (since there is no task context) +// For Real RTOS: fifo lock is a blocking API #if CFG_FIFO_MUTEX -#define mutex_lock_if_needed(_ff) if (_ff->mutex) tu_fifo_mutex_lock(_ff->mutex) -#define mutex_unlock_if_needed(_ff) if (_ff->mutex) tu_fifo_mutex_unlock(_ff->mutex) +static bool tu_fifo_lock(tu_fifo_t *f) +{ + if (f->mutex) + { +#if CFG_TUSB_OS == OPT_OS_NONE + // There is no subtask context for blocking mutex, we will check and return if cannot lock the mutex + if ( !osal_mutex_lock_notask(f->mutex) ) return false; +#else + uint32_t err; + (void) err; + osal_mutex_lock(f->mutex, OSAL_TIMEOUT_WAIT_FOREVER, &err); +#endif + } + + return true; +} + +static void tu_fifo_unlock(tu_fifo_t *f) +{ + if (f->mutex) + { + osal_mutex_unlock(f->mutex); + } +} #else -#define mutex_lock_if_needed(_ff) -#define mutex_unlock_if_needed(_ff) +#define tu_fifo_lock(_ff) true +#define tu_fifo_unlock(_ff) #endif -void tu_fifo_config(tu_fifo_t *f, void* buffer, uint16_t depth, uint16_t item_size, bool overwritable) +bool tu_fifo_config(tu_fifo_t *f, void* buffer, uint16_t depth, uint16_t item_size, bool overwritable) { - mutex_lock_if_needed(f); + if ( !tu_fifo_lock(f) ) return false; f->buffer = (uint8_t*) buffer; f->depth = depth; @@ -62,7 +89,9 @@ void tu_fifo_config(tu_fifo_t *f, void* buffer, uint16_t depth, uint16_t item_si f->rd_idx = f->wr_idx = f->count = 0; - mutex_unlock_if_needed(f); + tu_fifo_unlock(f); + + return true; } @@ -86,7 +115,7 @@ bool tu_fifo_read(tu_fifo_t* f, void * p_buffer) { if( tu_fifo_empty(f) ) return false; - mutex_lock_if_needed(f); + if ( !tu_fifo_lock(f) ) return false; memcpy(p_buffer, f->buffer + (f->rd_idx * f->item_size), @@ -94,7 +123,7 @@ bool tu_fifo_read(tu_fifo_t* f, void * p_buffer) f->rd_idx = (f->rd_idx + 1) % f->depth; f->count--; - mutex_unlock_if_needed(f); + tu_fifo_unlock(f); return true; } @@ -122,8 +151,6 @@ uint16_t tu_fifo_read_n (tu_fifo_t* f, void * p_buffer, uint16_t count) /* Limit up to fifo's count */ if ( count > f->count ) count = f->count; - mutex_lock_if_needed(f); - /* Could copy up to 2 portions marked as 'x' if queue is wrapped around * case 1: ....RxxxxW....... * case 2: xxxxxW....Rxxxxxx @@ -138,8 +165,6 @@ uint16_t tu_fifo_read_n (tu_fifo_t* f, void * p_buffer, uint16_t count) p_buf += f->item_size; } - mutex_unlock_if_needed(f); - return len; } @@ -189,10 +214,9 @@ bool tu_fifo_peek_at(tu_fifo_t* f, uint16_t pos, void * p_buffer) /******************************************************************************/ bool tu_fifo_write (tu_fifo_t* f, const void * p_data) { -// if ( tu_fifo_full(f) && !f->overwritable ) return false; - TU_ASSERT( !(tu_fifo_full(f) && !f->overwritable) ); + if ( tu_fifo_full(f) && !f->overwritable ) return false; - mutex_lock_if_needed(f); + if ( !tu_fifo_lock(f) ) return false; memcpy( f->buffer + (f->wr_idx * f->item_size), p_data, @@ -209,7 +233,7 @@ bool tu_fifo_write (tu_fifo_t* f, const void * p_data) f->count++; } - mutex_unlock_if_needed(f); + tu_fifo_unlock(f); return true; } @@ -233,7 +257,7 @@ uint16_t tu_fifo_write_n (tu_fifo_t* f, const void * p_data, uint16_t count) { if ( count == 0 ) return 0; - uint8_t* p_buf = (uint8_t*) p_data; + uint8_t const* p_buf = (uint8_t const*) p_data; uint16_t len = 0; while( (len < count) && tu_fifo_write(f, p_buf) ) @@ -253,11 +277,13 @@ uint16_t tu_fifo_write_n (tu_fifo_t* f, const void * p_data, uint16_t count) Pointer to the FIFO buffer to manipulate */ /******************************************************************************/ -void tu_fifo_clear(tu_fifo_t *f) +bool tu_fifo_clear(tu_fifo_t *f) { - mutex_lock_if_needed(f); + if ( !tu_fifo_lock(f) ) return false; f->rd_idx = f->wr_idx = f->count = 0; - mutex_unlock_if_needed(f); + tu_fifo_unlock(f); + + return true; } diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index 1ddf3bd94..70dc087c2 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -43,42 +43,17 @@ #ifndef _TUSB_FIFO_H_ #define _TUSB_FIFO_H_ -#define CFG_FIFO_MUTEX 0 +#define CFG_FIFO_MUTEX 1 #include #include -#include #ifdef __cplusplus extern "C" { #endif #if CFG_FIFO_MUTEX - -#include "osal/osal.h" - -#if CFG_TUSB_OS == OPT_OS_NONE -// Since all fifo read/write is done in thread mode, there should be -// no conflict except for osal queue which will be address seperatedly. -// Therefore there may be no need for mutex with internal use of fifo - -#define _ff_mutex_def(mutex) - -#else -#define tu_fifo_mutex_t struct os_mutex - -#define tu_fifo_mutex_lock(m) os_mutex_pend(m, OS_TIMEOUT_NEVER) -#define tu_fifo_mutex_unlock(m) os_mutex_release(m) - -/* Internal use only */ -#define _mutex_declare(m) .mutex = m - -#endif - -#else - -#define _mutex_declare(m) - +#define tu_fifo_mutex_t osal_mutex_t #endif @@ -98,24 +73,29 @@ typedef struct bool overwritable ; #if CFG_FIFO_MUTEX - tu_fifo_mutex_t * const mutex; + tu_fifo_mutex_t mutex; #endif } tu_fifo_t; -#define TU_FIFO_DEF(_name, _depth, _type, _overwritable) /*, irq_mutex)*/ \ - uint8_t _name##_buf[_depth*sizeof(_type)];\ - tu_fifo_t _name = {\ - .buffer = _name##_buf,\ - .depth = _depth,\ - .item_size = sizeof(_type),\ - .overwritable = _overwritable,\ - /*.irq = irq_mutex*/\ - _mutex_declare(_mutex)\ +#define TU_FIFO_DEF(_name, _depth, _type, _overwritable) \ + uint8_t _name##_buf[_depth*sizeof(_type)]; \ + tu_fifo_t _name = { \ + .buffer = _name##_buf, \ + .depth = _depth, \ + .item_size = sizeof(_type), \ + .overwritable = _overwritable, \ } -void tu_fifo_clear(tu_fifo_t *f); -void tu_fifo_config(tu_fifo_t *f, void* buffer, uint16_t depth, uint16_t item_size, bool overwritable); +bool tu_fifo_clear(tu_fifo_t *f); +bool tu_fifo_config(tu_fifo_t *f, void* buffer, uint16_t depth, uint16_t item_size, bool overwritable); + +#if CFG_FIFO_MUTEX +static inline void tu_fifo_config_mutex(tu_fifo_t *f, tu_fifo_mutex_t mutex_hdl) +{ + f->mutex = mutex_hdl; +} +#endif bool tu_fifo_write (tu_fifo_t* f, void const * p_data); uint16_t tu_fifo_write_n (tu_fifo_t* f, void const * p_data, uint16_t count); -- cgit v1.3.1 From 537a29273c08b1e047004e1bd71c37af82937dd4 Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Fri, 9 Nov 2018 00:10:44 -0800 Subject: Exempt from strict warnings for struct packing and add MCU options --- src/class/cdc/cdc.h | 6 ++++++ src/class/hid/hid.h | 5 +++++ src/class/msc/msc.h | 6 ++++++ src/common/tusb_types.h | 6 ++++++ src/portable/microchip/samd21/dcd.c | 2 +- src/tusb_option.h | 3 +++ 6 files changed, 27 insertions(+), 1 deletion(-) (limited to 'src/common') diff --git a/src/class/cdc/cdc.h b/src/class/cdc/cdc.h index 1b127ad28..0b6e57735 100644 --- a/src/class/cdc/cdc.h +++ b/src/class/cdc/cdc.h @@ -50,6 +50,10 @@ extern "C" { #endif +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wpacked" +#pragma GCC diagnostic ignored "-Wattributes" + /** \defgroup ClassDriver_CDC_Common Common Definitions * @{ */ @@ -401,6 +405,8 @@ typedef struct ATTR_PACKED TU_VERIFY_STATIC(sizeof(cdc_line_control_state_t) == 2, "size is not correct"); +#pragma GCC diagnostic pop + /** @} */ #ifdef __cplusplus diff --git a/src/class/hid/hid.h b/src/class/hid/hid.h index d2803177b..0008e47fb 100644 --- a/src/class/hid/hid.h +++ b/src/class/hid/hid.h @@ -49,6 +49,10 @@ extern "C" { #endif +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wpacked" +#pragma GCC diagnostic ignored "-Wattributes" + //--------------------------------------------------------------------+ // Common Definitions //--------------------------------------------------------------------+ @@ -609,6 +613,7 @@ enum HID_USAGE_CONSUMER_AC_PAN = 0x0238, }; +#pragma GCC diagnostic pop #ifdef __cplusplus } diff --git a/src/class/msc/msc.h b/src/class/msc/msc.h index a0abc2501..e7c32b303 100644 --- a/src/class/msc/msc.h +++ b/src/class/msc/msc.h @@ -52,6 +52,10 @@ extern "C" { #endif +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wpacked" +#pragma GCC diagnostic ignored "-Wattributes" + //--------------------------------------------------------------------+ // Mass Storage Class Constant //--------------------------------------------------------------------+ @@ -392,6 +396,8 @@ typedef struct ATTR_PACKED TU_VERIFY_STATIC(sizeof(scsi_read10_t) == 10, "size is not correct"); TU_VERIFY_STATIC(sizeof(scsi_write10_t) == 10, "size is not correct"); +#pragma GCC diagnostic pop + #ifdef __cplusplus } #endif diff --git a/src/common/tusb_types.h b/src/common/tusb_types.h index 8ce334e55..5c226f556 100644 --- a/src/common/tusb_types.h +++ b/src/common/tusb_types.h @@ -51,6 +51,10 @@ extern "C" { #endif +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wpacked" +#pragma GCC diagnostic ignored "-Wattributes" + /*------------------------------------------------------------------*/ /* CONSTANTS *------------------------------------------------------------------*/ @@ -422,6 +426,8 @@ static inline uint8_t descriptor_len(uint8_t const p_desc[]) // Convert comma-separated string to descriptor unicode format #define TUD_DESC_STRCONV( ... ) (const uint16_t[]) { TUD_DESC_STR_HEADER(VA_ARGS_NUM_(__VA_ARGS__)), __VA_ARGS__ } +#pragma GCC diagnostic pop + #ifdef __cplusplus } #endif diff --git a/src/portable/microchip/samd21/dcd.c b/src/portable/microchip/samd21/dcd.c index c9e88ad17..33cbc8d92 100644 --- a/src/portable/microchip/samd21/dcd.c +++ b/src/portable/microchip/samd21/dcd.c @@ -38,7 +38,7 @@ #include "tusb_option.h" -#if TUSB_OPT_DEVICE_ENABLED && CFG_TUSB_MCU == OPT_MCU_SAMD51 +#if TUSB_OPT_DEVICE_ENABLED && CFG_TUSB_MCU == OPT_MCU_SAMD21 #include "device/dcd.h" diff --git a/src/tusb_option.h b/src/tusb_option.h index d7a6c6fe0..d027ea0e6 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -57,6 +57,9 @@ #define OPT_MCU_LPC43XX 7 ///< NXP LPC43xx series #define OPT_MCU_NRF5X 100 ///< Nordic nRF5x series + +#define OPT_MCU_SAMD21 200 ///< MicroChip SAMD21 +#define OPT_MCU_SAMD51 201 ///< MicroChip SAMD51 /** @} */ /** \defgroup group_supported_os Supported RTOS -- cgit v1.3.1 From 3fe7cd165902948240ecc40468b3610686f579c3 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 13 Nov 2018 15:34:50 +0700 Subject: added tud_cdc_write_str, tu_fifo only use mutex for RTOS config --- examples/device/nrf52840/segger/SEGGER_RTT.c | 1329 -------------------- examples/device/nrf52840/segger/SEGGER_RTT.h | 234 ---- examples/device/nrf52840/segger/SEGGER_RTT_Conf.h | 242 ---- examples/device/nrf52840/segger/SEGGER_RTT_SES.c | 76 -- examples/device/nrf52840/segger/nrf52840.emProject | 12 +- examples/device/nrf52840/src/main.c | 83 +- .../device/nrf52840/src/segger_rtt/SEGGER_RTT.c | 1329 ++++++++++++++++++++ .../device/nrf52840/src/segger_rtt/SEGGER_RTT.h | 234 ++++ .../nrf52840/src/segger_rtt/SEGGER_RTT_Conf.h | 242 ++++ .../nrf52840/src/segger_rtt/SEGGER_RTT_SES.c | 76 ++ .../device/nrf52840_freertos/segger/SEGGER_RTT.c | 1329 -------------------- .../device/nrf52840_freertos/segger/SEGGER_RTT.h | 234 ---- .../nrf52840_freertos/segger/SEGGER_RTT_Conf.h | 242 ---- .../nrf52840_freertos/segger/SEGGER_RTT_SES.c | 76 -- .../segger/nrf5x_freertos.emProject | 12 +- examples/device/nrf52840_freertos/src/main.c | 26 +- .../nrf52840_freertos/src/segger_rtt/SEGGER_RTT.c | 1329 ++++++++++++++++++++ .../nrf52840_freertos/src/segger_rtt/SEGGER_RTT.h | 234 ++++ .../src/segger_rtt/SEGGER_RTT_Conf.h | 242 ++++ .../src/segger_rtt/SEGGER_RTT_SES.c | 76 ++ .../device/nrf52840_freertos/src/tusb_config.h | 2 +- hw/bsp/pca10056/board_pca10056.c | 5 + src/class/cdc/cdc_device.c | 13 +- src/class/cdc/cdc_device.h | 2 + src/common/tusb_fifo.c | 21 +- src/common/tusb_fifo.h | 4 +- src/osal/osal_none.h | 13 - 27 files changed, 3872 insertions(+), 3845 deletions(-) delete mode 100644 examples/device/nrf52840/segger/SEGGER_RTT.c delete mode 100644 examples/device/nrf52840/segger/SEGGER_RTT.h delete mode 100644 examples/device/nrf52840/segger/SEGGER_RTT_Conf.h delete mode 100644 examples/device/nrf52840/segger/SEGGER_RTT_SES.c create mode 100644 examples/device/nrf52840/src/segger_rtt/SEGGER_RTT.c create mode 100644 examples/device/nrf52840/src/segger_rtt/SEGGER_RTT.h create mode 100644 examples/device/nrf52840/src/segger_rtt/SEGGER_RTT_Conf.h create mode 100644 examples/device/nrf52840/src/segger_rtt/SEGGER_RTT_SES.c delete mode 100644 examples/device/nrf52840_freertos/segger/SEGGER_RTT.c delete mode 100644 examples/device/nrf52840_freertos/segger/SEGGER_RTT.h delete mode 100644 examples/device/nrf52840_freertos/segger/SEGGER_RTT_Conf.h delete mode 100644 examples/device/nrf52840_freertos/segger/SEGGER_RTT_SES.c create mode 100644 examples/device/nrf52840_freertos/src/segger_rtt/SEGGER_RTT.c create mode 100644 examples/device/nrf52840_freertos/src/segger_rtt/SEGGER_RTT.h create mode 100644 examples/device/nrf52840_freertos/src/segger_rtt/SEGGER_RTT_Conf.h create mode 100644 examples/device/nrf52840_freertos/src/segger_rtt/SEGGER_RTT_SES.c (limited to 'src/common') diff --git a/examples/device/nrf52840/segger/SEGGER_RTT.c b/examples/device/nrf52840/segger/SEGGER_RTT.c deleted file mode 100644 index aee5bd21e..000000000 --- a/examples/device/nrf52840/segger/SEGGER_RTT.c +++ /dev/null @@ -1,1329 +0,0 @@ -/********************************************************************* -* SEGGER MICROCONTROLLER GmbH & Co. KG * -* Solutions for real time microcontroller applications * -********************************************************************** -* * -* (c) 2014 - 2016 SEGGER Microcontroller GmbH & Co. KG * -* * -* www.segger.com Support: support@segger.com * -* * -********************************************************************** -* * -* SEGGER RTT * Real Time Transfer for embedded targets * -* * -********************************************************************** -* * -* All rights reserved. * -* * -* * This software may in its unmodified form be freely redistributed * -* in source form. * -* * The source code may be modified, provided the source code * -* retains the above copyright notice, this list of conditions and * -* the following disclaimer. * -* * Modified versions of this software in source or linkable form * -* may not be distributed without prior consent of SEGGER. * -* * This software may only be used for communication with SEGGER * -* J-Link debug probes. * -* * -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * -* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * -* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * -* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * -* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR * -* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * -* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * -* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * -* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * -* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * -* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * -* DAMAGE. * -* * -********************************************************************** -* * -* RTT version: 5.12e * -* * -********************************************************************** ----------------------------END-OF-HEADER------------------------------ -File : SEGGER_RTT.c -Purpose : Implementation of SEGGER real-time transfer (RTT) which - allows real-time communication on targets which support - debugger memory accesses while the CPU is running. - -Additional information: - Type "int" is assumed to be 32-bits in size - H->T Host to target communication - T->H Target to host communication - - RTT channel 0 is always present and reserved for Terminal usage. - Name is fixed to "Terminal" - - Effective buffer size: SizeOfBuffer - 1 - - WrOff == RdOff: Buffer is empty - WrOff == (RdOff - 1): Buffer is full - WrOff > RdOff: Free space includes wrap-around - WrOff < RdOff: Used space includes wrap-around - (WrOff == (SizeOfBuffer - 1)) && (RdOff == 0): - Buffer full and wrap-around after next byte - - ----------------------------------------------------------------------- -*/ - -#include "SEGGER_RTT.h" - -#include // for memcpy - -/********************************************************************* -* -* Configuration, default values -* -********************************************************************** -*/ - -#ifndef BUFFER_SIZE_UP - #define BUFFER_SIZE_UP 1024 // Size of the buffer for terminal output of target, up to host -#endif - -#ifndef BUFFER_SIZE_DOWN - #define BUFFER_SIZE_DOWN 16 // Size of the buffer for terminal input to target from host (Usually keyboard input) -#endif - -#ifndef SEGGER_RTT_MAX_NUM_UP_BUFFERS - #define SEGGER_RTT_MAX_NUM_UP_BUFFERS 2 // Number of up-buffers (T->H) available on this target -#endif - -#ifndef SEGGER_RTT_MAX_NUM_DOWN_BUFFERS - #define SEGGER_RTT_MAX_NUM_DOWN_BUFFERS 2 // Number of down-buffers (H->T) available on this target -#endif - -#ifndef SEGGER_RTT_BUFFER_SECTION - #if defined SEGGER_RTT_SECTION - #define SEGGER_RTT_BUFFER_SECTION SEGGER_RTT_SECTION - #endif -#endif - -#ifndef SEGGER_RTT_MODE_DEFAULT - #define SEGGER_RTT_MODE_DEFAULT SEGGER_RTT_MODE_NO_BLOCK_SKIP -#endif - -#ifndef SEGGER_RTT_LOCK - #define SEGGER_RTT_LOCK() -#endif - -#ifndef SEGGER_RTT_UNLOCK - #define SEGGER_RTT_UNLOCK() -#endif - -#ifndef STRLEN - #define STRLEN(a) strlen((a)) -#endif - -#ifndef MEMCPY - #define MEMCPY(pDest, pSrc, NumBytes) memcpy((pDest), (pSrc), (NumBytes)) -#endif - -#ifndef MIN - #define MIN(a, b) (((a) < (b)) ? (a) : (b)) -#endif - -#ifndef MAX - #define MAX(a, b) (((a) > (b)) ? (a) : (b)) -#endif -// -// For some environments, NULL may not be defined until certain headers are included -// -#ifndef NULL - #define NULL 0 -#endif - -/********************************************************************* -* -* Static const data -* -********************************************************************** -*/ - -static unsigned char _aTerminalId[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; - -/********************************************************************* -* -* Static data -* -********************************************************************** -*/ -// -// RTT Control Block and allocate buffers for channel 0 -// -#ifdef SEGGER_RTT_SECTION - #if (defined __GNUC__) - __attribute__ ((section (SEGGER_RTT_SECTION))) SEGGER_RTT_CB _SEGGER_RTT; - #elif (defined __ICCARM__) || (defined __ICCRX__) - #pragma location=SEGGER_RTT_SECTION - SEGGER_RTT_CB _SEGGER_RTT; - #elif (defined __CC_ARM__) - __attribute__ ((section (SEGGER_RTT_SECTION), zero_init)) SEGGER_RTT_CB _SEGGER_RTT; - #else - SEGGER_RTT_CB _SEGGER_RTT; - #endif -#else - SEGGER_RTT_CB _SEGGER_RTT; -#endif - -#ifdef SEGGER_RTT_BUFFER_SECTION - #if (defined __GNUC__) - __attribute__ ((section (SEGGER_RTT_BUFFER_SECTION))) static char _acUpBuffer [BUFFER_SIZE_UP]; - __attribute__ ((section (SEGGER_RTT_BUFFER_SECTION))) static char _acDownBuffer[BUFFER_SIZE_DOWN]; - #elif (defined __ICCARM__) || (defined __ICCRX__) - #pragma location=SEGGER_RTT_BUFFER_SECTION - static char _acUpBuffer [BUFFER_SIZE_UP]; - #pragma location=SEGGER_RTT_BUFFER_SECTION - static char _acDownBuffer[BUFFER_SIZE_DOWN]; - #elif (defined __CC_ARM__) - __attribute__ ((section (SEGGER_RTT_BUFFER_SECTION), zero_init)) static char _acUpBuffer [BUFFER_SIZE_UP]; - __attribute__ ((section (SEGGER_RTT_BUFFER_SECTION), zero_init)) static char _acDownBuffer[BUFFER_SIZE_DOWN]; - #else - static char _acUpBuffer [BUFFER_SIZE_UP]; - static char _acDownBuffer[BUFFER_SIZE_DOWN]; - #endif -#else - static char _acUpBuffer [BUFFER_SIZE_UP]; - static char _acDownBuffer[BUFFER_SIZE_DOWN]; -#endif - -static char _ActiveTerminal; - -/********************************************************************* -* -* Static functions -* -********************************************************************** -*/ - -/********************************************************************* -* -* _DoInit() -* -* Function description -* Initializes the control block an buffers. -* May only be called via INIT() to avoid overriding settings. -* -*/ -#define INIT() do { \ - if (_SEGGER_RTT.acID[0] == '\0') { _DoInit(); } \ - } while (0) -static void _DoInit(void) { - SEGGER_RTT_CB* p; - // - // Initialize control block - // - p = &_SEGGER_RTT; - p->MaxNumUpBuffers = SEGGER_RTT_MAX_NUM_UP_BUFFERS; - p->MaxNumDownBuffers = SEGGER_RTT_MAX_NUM_DOWN_BUFFERS; - // - // Initialize up buffer 0 - // - p->aUp[0].sName = "Terminal"; - p->aUp[0].pBuffer = _acUpBuffer; - p->aUp[0].SizeOfBuffer = sizeof(_acUpBuffer); - p->aUp[0].RdOff = 0u; - p->aUp[0].WrOff = 0u; - p->aUp[0].Flags = SEGGER_RTT_MODE_DEFAULT; - // - // Initialize down buffer 0 - // - p->aDown[0].sName = "Terminal"; - p->aDown[0].pBuffer = _acDownBuffer; - p->aDown[0].SizeOfBuffer = sizeof(_acDownBuffer); - p->aDown[0].RdOff = 0u; - p->aDown[0].WrOff = 0u; - p->aDown[0].Flags = SEGGER_RTT_MODE_DEFAULT; - // - // Finish initialization of the control block. - // Copy Id string in three steps to make sure "SEGGER RTT" is not found - // in initializer memory (usually flash) by J-Link - // - strcpy(&p->acID[7], "RTT"); - strcpy(&p->acID[0], "SEGGER"); - p->acID[6] = ' '; -} - -/********************************************************************* -* -* _WriteBlocking() -* -* Function description -* Stores a specified number of characters in SEGGER RTT ring buffer -* and updates the associated write pointer which is periodically -* read by the host. -* The caller is responsible for managing the write chunk sizes as -* _WriteBlocking() will block until all data has been posted successfully. -* -* Parameters -* pRing Ring buffer to post to. -* pBuffer Pointer to character array. Does not need to point to a \0 terminated string. -* NumBytes Number of bytes to be stored in the SEGGER RTT control block. -* -* Return value -* >= 0 - Number of bytes written into buffer. -*/ -static unsigned _WriteBlocking(SEGGER_RTT_BUFFER_UP* pRing, const char* pBuffer, unsigned NumBytes) { - unsigned NumBytesToWrite; - unsigned NumBytesWritten; - unsigned RdOff; - unsigned WrOff; - // - // Write data to buffer and handle wrap-around if necessary - // - NumBytesWritten = 0u; - WrOff = pRing->WrOff; - do { - RdOff = pRing->RdOff; // May be changed by host (debug probe) in the meantime - if (RdOff > WrOff) { - NumBytesToWrite = RdOff - WrOff - 1u; - } else { - NumBytesToWrite = pRing->SizeOfBuffer - (WrOff - RdOff + 1u); - } - NumBytesToWrite = MIN(NumBytesToWrite, (pRing->SizeOfBuffer - WrOff)); // Number of bytes that can be written until buffer wrap-around - NumBytesToWrite = MIN(NumBytesToWrite, NumBytes); - memcpy(pRing->pBuffer + WrOff, pBuffer, NumBytesToWrite); - NumBytesWritten += NumBytesToWrite; - pBuffer += NumBytesToWrite; - NumBytes -= NumBytesToWrite; - WrOff += NumBytesToWrite; - if (WrOff == pRing->SizeOfBuffer) { - WrOff = 0u; - } - pRing->WrOff = WrOff; - } while (NumBytes); - // - return NumBytesWritten; -} - -/********************************************************************* -* -* _WriteNoCheck() -* -* Function description -* Stores a specified number of characters in SEGGER RTT ring buffer -* and updates the associated write pointer which is periodically -* read by the host. -* It is callers responsibility to make sure data actually fits in buffer. -* -* Parameters -* pRing Ring buffer to post to. -* pBuffer Pointer to character array. Does not need to point to a \0 terminated string. -* NumBytes Number of bytes to be stored in the SEGGER RTT control block. -* -* Notes -* (1) If there might not be enough space in the "Up"-buffer, call _WriteBlocking -*/ -static void _WriteNoCheck(SEGGER_RTT_BUFFER_UP* pRing, const char* pData, unsigned NumBytes) { - unsigned NumBytesAtOnce; - unsigned WrOff; - unsigned Rem; - - WrOff = pRing->WrOff; - Rem = pRing->SizeOfBuffer - WrOff; - if (Rem > NumBytes) { - // - // All data fits before wrap around - // - memcpy(pRing->pBuffer + WrOff, pData, NumBytes); - pRing->WrOff = WrOff + NumBytes; - } else { - // - // We reach the end of the buffer, so need to wrap around - // - NumBytesAtOnce = Rem; - memcpy(pRing->pBuffer + WrOff, pData, NumBytesAtOnce); - NumBytesAtOnce = NumBytes - Rem; - memcpy(pRing->pBuffer, pData + Rem, NumBytesAtOnce); - pRing->WrOff = NumBytesAtOnce; - } -} - -/********************************************************************* -* -* _PostTerminalSwitch() -* -* Function description -* Switch terminal to the given terminal ID. It is the caller's -* responsibility to ensure the terminal ID is correct and there is -* enough space in the buffer for this to complete successfully. -* -* Parameters -* pRing Ring buffer to post to. -* TerminalId Terminal ID to switch to. -*/ -static void _PostTerminalSwitch(SEGGER_RTT_BUFFER_UP* pRing, unsigned char TerminalId) { - char ac[2]; - - ac[0] = 0xFFu; - ac[1] = _aTerminalId[TerminalId]; // Caller made already sure that TerminalId does not exceed our terminal limit - _WriteBlocking(pRing, ac, 2u); -} - -/********************************************************************* -* -* _GetAvailWriteSpace() -* -* Function description -* Returns the number of bytes that can be written to the ring -* buffer without blocking. -* -* Parameters -* pRing Ring buffer to check. -* -* Return value -* Number of bytes that are free in the buffer. -*/ -static unsigned _GetAvailWriteSpace(SEGGER_RTT_BUFFER_UP* pRing) { - unsigned RdOff; - unsigned WrOff; - unsigned r; - // - // Avoid warnings regarding volatile access order. It's not a problem - // in this case, but dampen compiler enthusiasm. - // - RdOff = pRing->RdOff; - WrOff = pRing->WrOff; - if (RdOff <= WrOff) { - r = pRing->SizeOfBuffer - 1u - WrOff + RdOff; - } else { - r = RdOff - WrOff - 1u; - } - return r; -} - -/********************************************************************* -* -* Public code -* -********************************************************************** -*/ -/********************************************************************* -* -* SEGGER_RTT_ReadNoLock() -* -* Function description -* Reads characters from SEGGER real-time-terminal control block -* which have been previously stored by the host. -* Do not lock against interrupts and multiple access. -* -* Parameters -* BufferIndex Index of Down-buffer to be used (e.g. 0 for "Terminal"). -* pBuffer Pointer to buffer provided by target application, to copy characters from RTT-down-buffer to. -* BufferSize Size of the target application buffer. -* -* Return value -* Number of bytes that have been read. -*/ -unsigned SEGGER_RTT_ReadNoLock(unsigned BufferIndex, void* pData, unsigned BufferSize) { - unsigned NumBytesRem; - unsigned NumBytesRead; - unsigned RdOff; - unsigned WrOff; - unsigned char* pBuffer; - SEGGER_RTT_BUFFER_DOWN* pRing; - // - INIT(); - pRing = &_SEGGER_RTT.aDown[BufferIndex]; - pBuffer = (unsigned char*)pData; - RdOff = pRing->RdOff; - WrOff = pRing->WrOff; - NumBytesRead = 0u; - // - // Read from current read position to wrap-around of buffer, first - // - if (RdOff > WrOff) { - NumBytesRem = pRing->SizeOfBuffer - RdOff; - NumBytesRem = MIN(NumBytesRem, BufferSize); - memcpy(pBuffer, pRing->pBuffer + RdOff, NumBytesRem); - NumBytesRead += NumBytesRem; - pBuffer += NumBytesRem; - BufferSize -= NumBytesRem; - RdOff += NumBytesRem; - // - // Handle wrap-around of buffer - // - if (RdOff == pRing->SizeOfBuffer) { - RdOff = 0u; - } - } - // - // Read remaining items of buffer - // - NumBytesRem = WrOff - RdOff; - NumBytesRem = MIN(NumBytesRem, BufferSize); - if (NumBytesRem > 0u) { - memcpy(pBuffer, pRing->pBuffer + RdOff, NumBytesRem); - NumBytesRead += NumBytesRem; - pBuffer += NumBytesRem; - BufferSize -= NumBytesRem; - RdOff += NumBytesRem; - } - if (NumBytesRead) { - pRing->RdOff = RdOff; - } - // - return NumBytesRead; -} - -/********************************************************************* -* -* SEGGER_RTT_Read -* -* Function description -* Reads characters from SEGGER real-time-terminal control block -* which have been previously stored by the host. -* -* Parameters -* BufferIndex Index of Down-buffer to be used (e.g. 0 for "Terminal"). -* pBuffer Pointer to buffer provided by target application, to copy characters from RTT-down-buffer to. -* BufferSize Size of the target application buffer. -* -* Return value -* Number of bytes that have been read. -*/ -unsigned SEGGER_RTT_Read(unsigned BufferIndex, void* pBuffer, unsigned BufferSize) { - unsigned NumBytesRead; - // - SEGGER_RTT_LOCK(); - // - // Call the non-locking read function - // - NumBytesRead = SEGGER_RTT_ReadNoLock(BufferIndex, pBuffer, BufferSize); - // - // Finish up. - // - SEGGER_RTT_UNLOCK(); - // - return NumBytesRead; -} - -/********************************************************************* -* -* SEGGER_RTT_WriteWithOverwriteNoLock -* -* Function description -* Stores a specified number of characters in SEGGER RTT -* control block. -* SEGGER_RTT_WriteWithOverwriteNoLock does not lock the application -* and overwrites data if the data does not fit into the buffer. -* -* Parameters -* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). -* pBuffer Pointer to character array. Does not need to point to a \0 terminated string. -* NumBytes Number of bytes to be stored in the SEGGER RTT control block. -* -* Notes -* (1) If there is not enough space in the "Up"-buffer, data is overwritten. -* (2) For performance reasons this function does not call Init() -* and may only be called after RTT has been initialized. -* Either by calling SEGGER_RTT_Init() or calling another RTT API function first. -* (3) Do not use SEGGER_RTT_WriteWithOverwriteNoLock if a J-Link -* connection reads RTT data. -*/ -void SEGGER_RTT_WriteWithOverwriteNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) { - const char* pData; - SEGGER_RTT_BUFFER_UP* pRing; - unsigned Avail; - - pData = (const char *)pBuffer; - // - // Get "to-host" ring buffer and copy some elements into local variables. - // - pRing = &_SEGGER_RTT.aUp[BufferIndex]; - // - // Check if we will overwrite data and need to adjust the RdOff. - // - if (pRing->WrOff == pRing->RdOff) { - Avail = pRing->SizeOfBuffer - 1u; - } else if ( pRing->WrOff < pRing->RdOff) { - Avail = pRing->RdOff - pRing->WrOff - 1u; - } else { - Avail = pRing->RdOff - pRing->WrOff - 1u + pRing->SizeOfBuffer; - } - if (NumBytes > Avail) { - pRing->RdOff += (NumBytes - Avail); - while (pRing->RdOff >= pRing->SizeOfBuffer) { - pRing->RdOff -= pRing->SizeOfBuffer; - } - } - // - // Write all data, no need to check the RdOff, but possibly handle multiple wrap-arounds - // - Avail = pRing->SizeOfBuffer - pRing->WrOff; - do { - if (Avail > NumBytes) { - // - // Last round - // -#if 1 // memcpy() is good for large amounts of data, but the overhead is too big for small amounts. Use a simple byte loop instead. - char* pDst; - pDst = pRing->pBuffer + pRing->WrOff; - pRing->WrOff += NumBytes; - do { - *pDst++ = *pData++; - } while (--NumBytes); -#else - memcpy(pRing->pBuffer + WrOff, pData, NumBytes); - pRing->WrOff += NumBytes; -#endif - break; //Alternatively: NumBytes = 0; - } else { - // - // Wrap-around necessary, write until wrap-around and reset WrOff - // - memcpy(pRing->pBuffer + pRing->WrOff, pData, Avail); - pData += Avail; - pRing->WrOff = 0; - NumBytes -= Avail; - Avail = (pRing->SizeOfBuffer - 1); - } - } while (NumBytes); -} - -/********************************************************************* -* -* SEGGER_RTT_WriteSkipNoLock -* -* Function description -* Stores a specified number of characters in SEGGER RTT -* control block which is then read by the host. -* SEGGER_RTT_WriteSkipNoLock does not lock the application and -* skips all data, if the data does not fit into the buffer. -* -* Parameters -* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). -* pBuffer Pointer to character array. Does not need to point to a \0 terminated string. -* NumBytes Number of bytes to be stored in the SEGGER RTT control block. -* -* Return value -* Number of bytes which have been stored in the "Up"-buffer. -* -* Notes -* (1) If there is not enough space in the "Up"-buffer, all data is dropped. -* (2) For performance reasons this function does not call Init() -* and may only be called after RTT has been initialized. -* Either by calling SEGGER_RTT_Init() or calling another RTT API function first. -*/ -unsigned SEGGER_RTT_WriteSkipNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) { - const char* pData; - SEGGER_RTT_BUFFER_UP* pRing; - unsigned Avail; - unsigned RdOff; - unsigned WrOff; - unsigned Rem; - - pData = (const char *)pBuffer; - // - // Get "to-host" ring buffer and copy some elements into local variables. - // - pRing = &_SEGGER_RTT.aUp[BufferIndex]; - RdOff = pRing->RdOff; - WrOff = pRing->WrOff; - // - // Handle the most common cases fastest. - // Which is: - // RdOff <= WrOff -> Space until wrap around is free. - // AND - // WrOff + NumBytes < SizeOfBuffer -> No Wrap around necessary. - // - // OR - // - // RdOff > WrOff -> Space until RdOff - 1 is free. - // AND - // WrOff + NumBytes < RdOff -> Data fits into buffer - // - if (RdOff <= WrOff) { - // - // Get space until WrOff will be at wrap around. - // - Avail = pRing->SizeOfBuffer - 1u - WrOff ; - if (Avail >= NumBytes) { -#if 1 // memcpy() is good for large amounts of data, but the overhead is too big for small amounts. Use a simple byte loop instead. - char* pDst; - pDst = pRing->pBuffer + WrOff; - WrOff += NumBytes; - do { - *pDst++ = *pData++; - } while (--NumBytes); - pRing->WrOff = WrOff + NumBytes; -#else - memcpy(pRing->pBuffer + WrOff, pData, NumBytes); - pRing->WrOff = WrOff + NumBytes; -#endif - return 1; - } - // - // If data did not fit into space until wrap around calculate complete space in buffer. - // - Avail += RdOff; - // - // If there is still no space for the whole of this output, don't bother. - // - if (Avail >= NumBytes) { - // - // OK, we have enough space in buffer. Copy in one or 2 chunks - // - Rem = pRing->SizeOfBuffer - WrOff; // Space until end of buffer - if (Rem > NumBytes) { - memcpy(pRing->pBuffer + WrOff, pData, NumBytes); - pRing->WrOff = WrOff + NumBytes; - } else { - // - // We reach the end of the buffer, so need to wrap around - // - memcpy(pRing->pBuffer + WrOff, pData, Rem); - memcpy(pRing->pBuffer, pData + Rem, NumBytes - Rem); - pRing->WrOff = NumBytes - Rem; - } - return 1; - } - } else { - Avail = RdOff - WrOff - 1u; - if (Avail >= NumBytes) { - memcpy(pRing->pBuffer + WrOff, pData, NumBytes); - pRing->WrOff = WrOff + NumBytes; - return 1; - } - } - // - // If we reach this point no data has been written - // - return 0; -} - -/********************************************************************* -* -* SEGGER_RTT_WriteNoLock -* -* Function description -* Stores a specified number of characters in SEGGER RTT -* control block which is then read by the host. -* SEGGER_RTT_WriteNoLock does not lock the application. -* -* Parameters -* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). -* pBuffer Pointer to character array. Does not need to point to a \0 terminated string. -* NumBytes Number of bytes to be stored in the SEGGER RTT control block. -* -* Return value -* Number of bytes which have been stored in the "Up"-buffer. -* -* Notes -* (1) If there is not enough space in the "Up"-buffer, remaining characters of pBuffer are dropped. -* (2) For performance reasons this function does not call Init() -* and may only be called after RTT has been initialized. -* Either by calling SEGGER_RTT_Init() or calling another RTT API function first. -*/ -unsigned SEGGER_RTT_WriteNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) { - unsigned Status; - unsigned Avail; - const char* pData; - SEGGER_RTT_BUFFER_UP* pRing; - - pData = (const char *)pBuffer; - // - // Get "to-host" ring buffer. - // - pRing = &_SEGGER_RTT.aUp[BufferIndex]; - // - // How we output depends upon the mode... - // - switch (pRing->Flags) { - case SEGGER_RTT_MODE_NO_BLOCK_SKIP: - // - // If we are in skip mode and there is no space for the whole - // of this output, don't bother. - // - Avail = _GetAvailWriteSpace(pRing); - if (Avail < NumBytes) { - Status = 0u; - } else { - Status = NumBytes; - _WriteNoCheck(pRing, pData, NumBytes); - } - break; - case SEGGER_RTT_MODE_NO_BLOCK_TRIM: - // - // If we are in trim mode, trim to what we can output without blocking. - // - Avail = _GetAvailWriteSpace(pRing); - Status = Avail < NumBytes ? Avail : NumBytes; - _WriteNoCheck(pRing, pData, Status); - break; - case SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL: - // - // If we are in blocking mode, output everything. - // - Status = _WriteBlocking(pRing, pData, NumBytes); - break; - default: - Status = 0u; - break; - } - // - // Finish up. - // - return Status; -} - -/********************************************************************* -* -* SEGGER_RTT_Write -* -* Function description -* Stores a specified number of characters in SEGGER RTT -* control block which is then read by the host. -* -* Parameters -* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). -* pBuffer Pointer to character array. Does not need to point to a \0 terminated string. -* NumBytes Number of bytes to be stored in the SEGGER RTT control block. -* -* Return value -* Number of bytes which have been stored in the "Up"-buffer. -* -* Notes -* (1) If there is not enough space in the "Up"-buffer, remaining characters of pBuffer are dropped. -*/ -unsigned SEGGER_RTT_Write(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) { - unsigned Status; - // - INIT(); - SEGGER_RTT_LOCK(); - // - // Call the non-locking write function - // - Status = SEGGER_RTT_WriteNoLock(BufferIndex, pBuffer, NumBytes); - // - // Finish up. - // - SEGGER_RTT_UNLOCK(); - // - return Status; -} - -/********************************************************************* -* -* SEGGER_RTT_WriteString -* -* Function description -* Stores string in SEGGER RTT control block. -* This data is read by the host. -* -* Parameters -* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). -* s Pointer to string. -* -* Return value -* Number of bytes which have been stored in the "Up"-buffer. -* -* Notes -* (1) If there is not enough space in the "Up"-buffer, depending on configuration, -* remaining characters may be dropped or RTT module waits until there is more space in the buffer. -* (2) String passed to this function has to be \0 terminated -* (3) \0 termination character is *not* stored in RTT buffer -*/ -unsigned SEGGER_RTT_WriteString(unsigned BufferIndex, const char* s) { - unsigned Len; - - Len = STRLEN(s); - return SEGGER_RTT_Write(BufferIndex, s, Len); -} - -/********************************************************************* -* -* SEGGER_RTT_GetKey -* -* Function description -* Reads one character from the SEGGER RTT buffer. -* Host has previously stored data there. -* -* Return value -* < 0 - No character available (buffer empty). -* >= 0 - Character which has been read. (Possible values: 0 - 255) -* -* Notes -* (1) This function is only specified for accesses to RTT buffer 0. -*/ -int SEGGER_RTT_GetKey(void) { - char c; - int r; - - r = (int)SEGGER_RTT_Read(0u, &c, 1u); - if (r == 1) { - r = (int)(unsigned char)c; - } else { - r = -1; - } - return r; -} - -/********************************************************************* -* -* SEGGER_RTT_WaitKey -* -* Function description -* Waits until at least one character is avaible in the SEGGER RTT buffer. -* Once a character is available, it is read and this function returns. -* -* Return value -* >=0 - Character which has been read. -* -* Notes -* (1) This function is only specified for accesses to RTT buffer 0 -* (2) This function is blocking if no character is present in RTT buffer -*/ -int SEGGER_RTT_WaitKey(void) { - int r; - - do { - r = SEGGER_RTT_GetKey(); - } while (r < 0); - return r; -} - -/********************************************************************* -* -* SEGGER_RTT_HasKey -* -* Function description -* Checks if at least one character for reading is available in the SEGGER RTT buffer. -* -* Return value -* == 0 - No characters are available to read. -* == 1 - At least one character is available. -* -* Notes -* (1) This function is only specified for accesses to RTT buffer 0 -*/ -int SEGGER_RTT_HasKey(void) { - unsigned RdOff; - int r; - - INIT(); - RdOff = _SEGGER_RTT.aDown[0].RdOff; - if (RdOff != _SEGGER_RTT.aDown[0].WrOff) { - r = 1; - } else { - r = 0; - } - return r; -} - -/********************************************************************* -* -* SEGGER_RTT_HasData -* -* Function description -* Check if there is data from the host in the given buffer. -* -* Return value: -* ==0: No data -* !=0: Data in buffer -* -*/ -unsigned SEGGER_RTT_HasData(unsigned BufferIndex) { - SEGGER_RTT_BUFFER_DOWN* pRing; - unsigned v; - - pRing = &_SEGGER_RTT.aDown[BufferIndex]; - v = pRing->WrOff; - return v - pRing->RdOff; -} - -/********************************************************************* -* -* SEGGER_RTT_AllocDownBuffer -* -* Function description -* Run-time configuration of the next down-buffer (H->T). -* The next buffer, which is not used yet is configured. -* This includes: Buffer address, size, name, flags, ... -* -* Parameters -* sName Pointer to a constant name string. -* pBuffer Pointer to a buffer to be used. -* BufferSize Size of the buffer. -* Flags Operating modes. Define behavior if buffer is full (not enough space for entire message). -* -* Return value -* >= 0 - O.K. Buffer Index -* < 0 - Error -*/ -int SEGGER_RTT_AllocDownBuffer(const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) { - int BufferIndex; - - INIT(); - SEGGER_RTT_LOCK(); - BufferIndex = 0; - do { - if (_SEGGER_RTT.aDown[BufferIndex].pBuffer == NULL) { - break; - } - BufferIndex++; - } while (BufferIndex < _SEGGER_RTT.MaxNumDownBuffers); - if (BufferIndex < _SEGGER_RTT.MaxNumDownBuffers) { - _SEGGER_RTT.aDown[BufferIndex].sName = sName; - _SEGGER_RTT.aDown[BufferIndex].pBuffer = pBuffer; - _SEGGER_RTT.aDown[BufferIndex].SizeOfBuffer = BufferSize; - _SEGGER_RTT.aDown[BufferIndex].RdOff = 0u; - _SEGGER_RTT.aDown[BufferIndex].WrOff = 0u; - _SEGGER_RTT.aDown[BufferIndex].Flags = Flags; - } else { - BufferIndex = -1; - } - SEGGER_RTT_UNLOCK(); - return BufferIndex; -} - -/********************************************************************* -* -* SEGGER_RTT_AllocUpBuffer -* -* Function description -* Run-time configuration of the next up-buffer (T->H). -* The next buffer, which is not used yet is configured. -* This includes: Buffer address, size, name, flags, ... -* -* Parameters -* sName Pointer to a constant name string. -* pBuffer Pointer to a buffer to be used. -* BufferSize Size of the buffer. -* Flags Operating modes. Define behavior if buffer is full (not enough space for entire message). -* -* Return value -* >= 0 - O.K. Buffer Index -* < 0 - Error -*/ -int SEGGER_RTT_AllocUpBuffer(const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) { - int BufferIndex; - - INIT(); - SEGGER_RTT_LOCK(); - BufferIndex = 0; - do { - if (_SEGGER_RTT.aUp[BufferIndex].pBuffer == NULL) { - break; - } - BufferIndex++; - } while (BufferIndex < _SEGGER_RTT.MaxNumUpBuffers); - if (BufferIndex < _SEGGER_RTT.MaxNumUpBuffers) { - _SEGGER_RTT.aUp[BufferIndex].sName = sName; - _SEGGER_RTT.aUp[BufferIndex].pBuffer = pBuffer; - _SEGGER_RTT.aUp[BufferIndex].SizeOfBuffer = BufferSize; - _SEGGER_RTT.aUp[BufferIndex].RdOff = 0u; - _SEGGER_RTT.aUp[BufferIndex].WrOff = 0u; - _SEGGER_RTT.aUp[BufferIndex].Flags = Flags; - } else { - BufferIndex = -1; - } - SEGGER_RTT_UNLOCK(); - return BufferIndex; -} - -/********************************************************************* -* -* SEGGER_RTT_ConfigUpBuffer -* -* Function description -* Run-time configuration of a specific up-buffer (T->H). -* Buffer to be configured is specified by index. -* This includes: Buffer address, size, name, flags, ... -* -* Parameters -* BufferIndex Index of the buffer to configure. -* sName Pointer to a constant name string. -* pBuffer Pointer to a buffer to be used. -* BufferSize Size of the buffer. -* Flags Operating modes. Define behavior if buffer is full (not enough space for entire message). -* -* Return value -* >= 0 - O.K. -* < 0 - Error -*/ -int SEGGER_RTT_ConfigUpBuffer(unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) { - int r; - - INIT(); - if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumUpBuffers) { - SEGGER_RTT_LOCK(); - if (BufferIndex > 0u) { - _SEGGER_RTT.aUp[BufferIndex].sName = sName; - _SEGGER_RTT.aUp[BufferIndex].pBuffer = pBuffer; - _SEGGER_RTT.aUp[BufferIndex].SizeOfBuffer = BufferSize; - _SEGGER_RTT.aUp[BufferIndex].RdOff = 0u; - _SEGGER_RTT.aUp[BufferIndex].WrOff = 0u; - } - _SEGGER_RTT.aUp[BufferIndex].Flags = Flags; - SEGGER_RTT_UNLOCK(); - r = 0; - } else { - r = -1; - } - return r; -} - -/********************************************************************* -* -* SEGGER_RTT_ConfigDownBuffer -* -* Function description -* Run-time configuration of a specific down-buffer (H->T). -* Buffer to be configured is specified by index. -* This includes: Buffer address, size, name, flags, ... -* -* Parameters -* BufferIndex Index of the buffer to configure. -* sName Pointer to a constant name string. -* pBuffer Pointer to a buffer to be used. -* BufferSize Size of the buffer. -* Flags Operating modes. Define behavior if buffer is full (not enough space for entire message). -* -* Return value -* >= 0 O.K. -* < 0 Error -*/ -int SEGGER_RTT_ConfigDownBuffer(unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) { - int r; - - INIT(); - if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumDownBuffers) { - SEGGER_RTT_LOCK(); - if (BufferIndex > 0u) { - _SEGGER_RTT.aDown[BufferIndex].sName = sName; - _SEGGER_RTT.aDown[BufferIndex].pBuffer = pBuffer; - _SEGGER_RTT.aDown[BufferIndex].SizeOfBuffer = BufferSize; - _SEGGER_RTT.aDown[BufferIndex].RdOff = 0u; - _SEGGER_RTT.aDown[BufferIndex].WrOff = 0u; - } - _SEGGER_RTT.aDown[BufferIndex].Flags = Flags; - SEGGER_RTT_UNLOCK(); - r = 0; - } else { - r = -1; - } - return r; -} - -/********************************************************************* -* -* SEGGER_RTT_SetNameUpBuffer -* -* Function description -* Run-time configuration of a specific up-buffer name (T->H). -* Buffer to be configured is specified by index. -* -* Parameters -* BufferIndex Index of the buffer to renamed. -* sName Pointer to a constant name string. -* -* Return value -* >= 0 O.K. -* < 0 Error -*/ -int SEGGER_RTT_SetNameUpBuffer(unsigned BufferIndex, const char* sName) { - int r; - - INIT(); - if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumUpBuffers) { - SEGGER_RTT_LOCK(); - _SEGGER_RTT.aUp[BufferIndex].sName = sName; - SEGGER_RTT_UNLOCK(); - r = 0; - } else { - r = -1; - } - return r; -} - -/********************************************************************* -* -* SEGGER_RTT_SetNameDownBuffer -* -* Function description -* Run-time configuration of a specific Down-buffer name (T->H). -* Buffer to be configured is specified by index. -* -* Parameters -* BufferIndex Index of the buffer to renamed. -* sName Pointer to a constant name string. -* -* Return value -* >= 0 O.K. -* < 0 Error -*/ -int SEGGER_RTT_SetNameDownBuffer(unsigned BufferIndex, const char* sName) { - int r; - - INIT(); - if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumDownBuffers) { - SEGGER_RTT_LOCK(); - _SEGGER_RTT.aDown[BufferIndex].sName = sName; - SEGGER_RTT_UNLOCK(); - r = 0; - } else { - r = -1; - } - return r; -} - -/********************************************************************* -* -* SEGGER_RTT_Init -* -* Function description -* Initializes the RTT Control Block. -* Should be used in RAM targets, at start of the application. -* -*/ -void SEGGER_RTT_Init (void) { - _DoInit(); -} - -/********************************************************************* -* -* SEGGER_RTT_SetTerminal -* -* Function description -* Sets the terminal to be used for output on channel 0. -* -* Parameters -* TerminalId Index of the terminal. -* -* Return value -* >= 0 O.K. -* < 0 Error (e.g. if RTT is configured for non-blocking mode and there was no space in the buffer to set the new terminal Id) -*/ -int SEGGER_RTT_SetTerminal (char TerminalId) { - char ac[2]; - SEGGER_RTT_BUFFER_UP* pRing; - unsigned Avail; - int r; - // - INIT(); - // - r = 0; - ac[0] = 0xFFU; - if ((unsigned char)TerminalId < (unsigned char)sizeof(_aTerminalId)) { // We only support a certain number of channels - ac[1] = _aTerminalId[(unsigned char)TerminalId]; - pRing = &_SEGGER_RTT.aUp[0]; // Buffer 0 is always reserved for terminal I/O, so we can use index 0 here, fixed - SEGGER_RTT_LOCK(); // Lock to make sure that no other task is writing into buffer, while we are and number of free bytes in buffer does not change downwards after checking and before writing - if ((pRing->Flags & SEGGER_RTT_MODE_MASK) == SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL) { - _ActiveTerminal = TerminalId; - _WriteBlocking(pRing, ac, 2u); - } else { // Skipping mode or trim mode? => We cannot trim this command so handling is the same for both modes - Avail = _GetAvailWriteSpace(pRing); - if (Avail >= 2) { - _ActiveTerminal = TerminalId; // Only change active terminal in case of success - _WriteNoCheck(pRing, ac, 2u); - } else { - r = -1; - } - } - SEGGER_RTT_UNLOCK(); - } else { - r = -1; - } - return r; -} - -/********************************************************************* -* -* SEGGER_RTT_TerminalOut -* -* Function description -* Writes a string to the given terminal -* without changing the terminal for channel 0. -* -* Parameters -* TerminalId Index of the terminal. -* s String to be printed on the terminal. -* -* Return value -* >= 0 - Number of bytes written. -* < 0 - Error. -* -*/ -int SEGGER_RTT_TerminalOut (char TerminalId, const char* s) { - int Status; - unsigned FragLen; - unsigned Avail; - SEGGER_RTT_BUFFER_UP* pRing; - // - INIT(); - // - // Validate terminal ID. - // - if (TerminalId < (char)sizeof(_aTerminalId)) { // We only support a certain number of channels - // - // Get "to-host" ring buffer. - // - pRing = &_SEGGER_RTT.aUp[0]; - // - // Need to be able to change terminal, write data, change back. - // Compute the fixed and variable sizes. - // - FragLen = strlen(s); - // - // How we output depends upon the mode... - // - SEGGER_RTT_LOCK(); - Avail = _GetAvailWriteSpace(pRing); - switch (pRing->Flags & SEGGER_RTT_MODE_MASK) { - case SEGGER_RTT_MODE_NO_BLOCK_SKIP: - // - // If we are in skip mode and there is no space for the whole - // of this output, don't bother switching terminals at all. - // - if (Avail < (FragLen + 4u)) { - Status = 0; - } else { - _PostTerminalSwitch(pRing, TerminalId); - Status = (int)_WriteBlocking(pRing, s, FragLen); - _PostTerminalSwitch(pRing, _ActiveTerminal); - } - break; - case SEGGER_RTT_MODE_NO_BLOCK_TRIM: - // - // If we are in trim mode and there is not enough space for everything, - // trim the output but always include the terminal switch. If no room - // for terminal switch, skip that totally. - // - if (Avail < 4u) { - Status = -1; - } else { - _PostTerminalSwitch(pRing, TerminalId); - Status = (int)_WriteBlocking(pRing, s, (FragLen < (Avail - 4u)) ? FragLen : (Avail - 4u)); - _PostTerminalSwitch(pRing, _ActiveTerminal); - } - break; - case SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL: - // - // If we are in blocking mode, output everything. - // - _PostTerminalSwitch(pRing, TerminalId); - Status = (int)_WriteBlocking(pRing, s, FragLen); - _PostTerminalSwitch(pRing, _ActiveTerminal); - break; - default: - Status = -1; - break; - } - // - // Finish up. - // - SEGGER_RTT_UNLOCK(); - } else { - Status = -1; - } - return Status; -} - - -/*************************** End of file ****************************/ diff --git a/examples/device/nrf52840/segger/SEGGER_RTT.h b/examples/device/nrf52840/segger/SEGGER_RTT.h deleted file mode 100644 index d3cac44dd..000000000 --- a/examples/device/nrf52840/segger/SEGGER_RTT.h +++ /dev/null @@ -1,234 +0,0 @@ -/********************************************************************* -* SEGGER MICROCONTROLLER GmbH & Co. KG * -* Solutions for real time microcontroller applications * -********************************************************************** -* * -* (c) 2014 - 2016 SEGGER Microcontroller GmbH & Co. KG * -* * -* www.segger.com Support: support@segger.com * -* * -********************************************************************** -* * -* SEGGER RTT * Real Time Transfer for embedded targets * -* * -********************************************************************** -* * -* All rights reserved. * -* * -* * This software may in its unmodified form be freely redistributed * -* in source form. * -* * The source code may be modified, provided the source code * -* retains the above copyright notice, this list of conditions and * -* the following disclaimer. * -* * Modified versions of this software in source or linkable form * -* may not be distributed without prior consent of SEGGER. * -* * This software may only be used for communication with SEGGER * -* J-Link debug probes. * -* * -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * -* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * -* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * -* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * -* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR * -* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * -* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * -* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * -* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * -* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * -* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * -* DAMAGE. * -* * -********************************************************************** -* * -* RTT version: 5.12e * -* * -********************************************************************** ----------------------------END-OF-HEADER------------------------------ -File : SEGGER_RTT.h -Purpose : Implementation of SEGGER real-time transfer which allows - real-time communication on targets which support debugger - memory accesses while the CPU is running. ----------------------------------------------------------------------- -*/ - -#ifndef SEGGER_RTT_H -#define SEGGER_RTT_H - -#include "SEGGER_RTT_Conf.h" - -/********************************************************************* -* -* Defines, fixed -* -********************************************************************** -*/ - -/********************************************************************* -* -* Types -* -********************************************************************** -*/ - -// -// Description for a circular buffer (also called "ring buffer") -// which is used as up-buffer (T->H) -// -typedef struct { - const char* sName; // Optional name. Standard names so far are: "Terminal", "SysView", "J-Scope_t4i4" - char* pBuffer; // Pointer to start of buffer - unsigned SizeOfBuffer; // Buffer size in bytes. Note that one byte is lost, as this implementation does not fill up the buffer in order to avoid the problem of being unable to distinguish between full and empty. - unsigned WrOff; // Position of next item to be written by either target. - volatile unsigned RdOff; // Position of next item to be read by host. Must be volatile since it may be modified by host. - unsigned Flags; // Contains configuration flags -} SEGGER_RTT_BUFFER_UP; - -// -// Description for a circular buffer (also called "ring buffer") -// which is used as down-buffer (H->T) -// -typedef struct { - const char* sName; // Optional name. Standard names so far are: "Terminal", "SysView", "J-Scope_t4i4" - char* pBuffer; // Pointer to start of buffer - unsigned SizeOfBuffer; // Buffer size in bytes. Note that one byte is lost, as this implementation does not fill up the buffer in order to avoid the problem of being unable to distinguish between full and empty. - volatile unsigned WrOff; // Position of next item to be written by host. Must be volatile since it may be modified by host. - unsigned RdOff; // Position of next item to be read by target (down-buffer). - unsigned Flags; // Contains configuration flags -} SEGGER_RTT_BUFFER_DOWN; - -// -// RTT control block which describes the number of buffers available -// as well as the configuration for each buffer -// -// -typedef struct { - char acID[16]; // Initialized to "SEGGER RTT" - int MaxNumUpBuffers; // Initialized to SEGGER_RTT_MAX_NUM_UP_BUFFERS (type. 2) - int MaxNumDownBuffers; // Initialized to SEGGER_RTT_MAX_NUM_DOWN_BUFFERS (type. 2) - SEGGER_RTT_BUFFER_UP aUp[SEGGER_RTT_MAX_NUM_UP_BUFFERS]; // Up buffers, transferring information up from target via debug probe to host - SEGGER_RTT_BUFFER_DOWN aDown[SEGGER_RTT_MAX_NUM_DOWN_BUFFERS]; // Down buffers, transferring information down from host via debug probe to target -} SEGGER_RTT_CB; - -/********************************************************************* -* -* Global data -* -********************************************************************** -*/ -extern SEGGER_RTT_CB _SEGGER_RTT; - -/********************************************************************* -* -* RTT API functions -* -********************************************************************** -*/ -#ifdef __cplusplus - extern "C" { -#endif -int SEGGER_RTT_AllocDownBuffer (const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags); -int SEGGER_RTT_AllocUpBuffer (const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags); -int SEGGER_RTT_ConfigUpBuffer (unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags); -int SEGGER_RTT_ConfigDownBuffer (unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags); -int SEGGER_RTT_GetKey (void); -unsigned SEGGER_RTT_HasData (unsigned BufferIndex); -int SEGGER_RTT_HasKey (void); -void SEGGER_RTT_Init (void); -unsigned SEGGER_RTT_Read (unsigned BufferIndex, void* pBuffer, unsigned BufferSize); -unsigned SEGGER_RTT_ReadNoLock (unsigned BufferIndex, void* pData, unsigned BufferSize); -int SEGGER_RTT_SetNameDownBuffer(unsigned BufferIndex, const char* sName); -int SEGGER_RTT_SetNameUpBuffer (unsigned BufferIndex, const char* sName); -int SEGGER_RTT_WaitKey (void); -unsigned SEGGER_RTT_Write (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes); -unsigned SEGGER_RTT_WriteNoLock (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes); -unsigned SEGGER_RTT_WriteSkipNoLock (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes); -unsigned SEGGER_RTT_WriteString (unsigned BufferIndex, const char* s); -void SEGGER_RTT_WriteWithOverwriteNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes); -// -// Function macro for performance optimization -// -#define SEGGER_RTT_HASDATA(n) (_SEGGER_RTT.aDown[n].WrOff - _SEGGER_RTT.aDown[n].RdOff) - -/********************************************************************* -* -* RTT "Terminal" API functions -* -********************************************************************** -*/ -int SEGGER_RTT_SetTerminal (char TerminalId); -int SEGGER_RTT_TerminalOut (char TerminalId, const char* s); - -/********************************************************************* -* -* RTT printf functions (require SEGGER_RTT_printf.c) -* -********************************************************************** -*/ -int SEGGER_RTT_printf(unsigned BufferIndex, const char * sFormat, ...); -#ifdef __cplusplus - } -#endif - -/********************************************************************* -* -* Defines -* -********************************************************************** -*/ - -// -// Operating modes. Define behavior if buffer is full (not enough space for entire message) -// -#define SEGGER_RTT_MODE_NO_BLOCK_SKIP (0U) // Skip. Do not block, output nothing. (Default) -#define SEGGER_RTT_MODE_NO_BLOCK_TRIM (1U) // Trim: Do not block, output as much as fits. -#define SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL (2U) // Block: Wait until there is space in the buffer. -#define SEGGER_RTT_MODE_MASK (3U) - -// -// Control sequences, based on ANSI. -// Can be used to control color, and clear the screen -// -#define RTT_CTRL_RESET "" // Reset to default colors -#define RTT_CTRL_CLEAR "" // Clear screen, reposition cursor to top left - -#define RTT_CTRL_TEXT_BLACK "" -#define RTT_CTRL_TEXT_RED "" -#define RTT_CTRL_TEXT_GREEN "" -#define RTT_CTRL_TEXT_YELLOW "" -#define RTT_CTRL_TEXT_BLUE "" -#define RTT_CTRL_TEXT_MAGENTA "" -#define RTT_CTRL_TEXT_CYAN "" -#define RTT_CTRL_TEXT_WHITE "" - -#define RTT_CTRL_TEXT_BRIGHT_BLACK "" -#define RTT_CTRL_TEXT_BRIGHT_RED "" -#define RTT_CTRL_TEXT_BRIGHT_GREEN "" -#define RTT_CTRL_TEXT_BRIGHT_YELLOW "" -#define RTT_CTRL_TEXT_BRIGHT_BLUE "" -#define RTT_CTRL_TEXT_BRIGHT_MAGENTA "" -#define RTT_CTRL_TEXT_BRIGHT_CYAN "" -#define RTT_CTRL_TEXT_BRIGHT_WHITE "" - -#define RTT_CTRL_BG_BLACK "" -#define RTT_CTRL_BG_RED "" -#define RTT_CTRL_BG_GREEN "" -#define RTT_CTRL_BG_YELLOW "" -#define RTT_CTRL_BG_BLUE "" -#define RTT_CTRL_BG_MAGENTA "" -#define RTT_CTRL_BG_CYAN "" -#define RTT_CTRL_BG_WHITE "" - -#define RTT_CTRL_BG_BRIGHT_BLACK "" -#define RTT_CTRL_BG_BRIGHT_RED "" -#define RTT_CTRL_BG_BRIGHT_GREEN "" -#define RTT_CTRL_BG_BRIGHT_YELLOW "" -#define RTT_CTRL_BG_BRIGHT_BLUE "" -#define RTT_CTRL_BG_BRIGHT_MAGENTA "" -#define RTT_CTRL_BG_BRIGHT_CYAN "" -#define RTT_CTRL_BG_BRIGHT_WHITE "" - - -#endif - -/*************************** End of file ****************************/ diff --git a/examples/device/nrf52840/segger/SEGGER_RTT_Conf.h b/examples/device/nrf52840/segger/SEGGER_RTT_Conf.h deleted file mode 100644 index aef3b4053..000000000 --- a/examples/device/nrf52840/segger/SEGGER_RTT_Conf.h +++ /dev/null @@ -1,242 +0,0 @@ -/********************************************************************* -* SEGGER MICROCONTROLLER GmbH & Co. KG * -* Solutions for real time microcontroller applications * -********************************************************************** -* * -* (c) 2014 - 2016 SEGGER Microcontroller GmbH & Co. KG * -* * -* www.segger.com Support: support@segger.com * -* * -********************************************************************** -* * -* SEGGER RTT * Real Time Transfer for embedded targets * -* * -********************************************************************** -* * -* All rights reserved. * -* * -* * This software may in its unmodified form be freely redistributed * -* in source form. * -* * The source code may be modified, provided the source code * -* retains the above copyright notice, this list of conditions and * -* the following disclaimer. * -* * Modified versions of this software in source or linkable form * -* may not be distributed without prior consent of SEGGER. * -* * This software may only be used for communication with SEGGER * -* J-Link debug probes. * -* * -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * -* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * -* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * -* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * -* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR * -* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * -* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * -* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * -* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * -* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * -* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * -* DAMAGE. * -* * -********************************************************************** -* * -* RTT version: 5.12e * -* * -********************************************************************** ----------------------------------------------------------------------- -File : SEGGER_RTT_Conf.h -Purpose : Implementation of SEGGER real-time transfer (RTT) which - allows real-time communication on targets which support - debugger memory accesses while the CPU is running. ----------------------------END-OF-HEADER------------------------------ -*/ - -#ifndef SEGGER_RTT_CONF_H -#define SEGGER_RTT_CONF_H - -#ifdef __ICCARM__ - #include -#endif - -/********************************************************************* -* -* Defines, configurable -* -********************************************************************** -*/ - -#define SEGGER_RTT_MAX_NUM_UP_BUFFERS (2) // Max. number of up-buffers (T->H) available on this target (Default: 2) -#define SEGGER_RTT_MAX_NUM_DOWN_BUFFERS (2) // Max. number of down-buffers (H->T) available on this target (Default: 2) - -#define BUFFER_SIZE_UP (1024) // Size of the buffer for terminal output of target, up to host (Default: 1k) -#define BUFFER_SIZE_DOWN (16) // Size of the buffer for terminal input to target from host (Usually keyboard input) (Default: 16) - -#define SEGGER_RTT_PRINTF_BUFFER_SIZE (64u) // Size of buffer for RTT printf to bulk-send chars via RTT (Default: 64) - -#define SEGGER_RTT_MODE_DEFAULT SEGGER_RTT_MODE_NO_BLOCK_SKIP // Mode for pre-initialized terminal channel (buffer 0) - -// -// Target is not allowed to perform other RTT operations while string still has not been stored completely. -// Otherwise we would probably end up with a mixed string in the buffer. -// If using RTT from within interrupts, multiple tasks or multi processors, define the SEGGER_RTT_LOCK() and SEGGER_RTT_UNLOCK() function here. -// -// SEGGER_RTT_MAX_INTERRUPT_PRIORITY can be used in the sample lock routines on Cortex-M3/4. -// Make sure to mask all interrupts which can send RTT data, i.e. generate SystemView events, or cause task switches. -// When high-priority interrupts must not be masked while sending RTT data, SEGGER_RTT_MAX_INTERRUPT_PRIORITY needs to be adjusted accordingly. -// (Higher priority = lower priority number) -// Default value for embOS: 128u -// Default configuration in FreeRTOS: configMAX_SYSCALL_INTERRUPT_PRIORITY: ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) ) -// In case of doubt mask all interrupts: 0u -// - -#define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20) // Interrupt priority to lock on SEGGER_RTT_LOCK on Cortex-M3/4 (Default: 0x20) - -/********************************************************************* -* -* RTT lock configuration for SEGGER Embedded Studio, -* Rowley CrossStudio and GCC -*/ -#if (defined __SES_ARM) || (defined __CROSSWORKS_ARM) || (defined __GNUC__) - #ifdef __ARM_ARCH_6M__ - #define SEGGER_RTT_LOCK() { \ - unsigned int LockState; \ - __asm volatile ("mrs %0, primask \n\t" \ - "mov r1, $1 \n\t" \ - "msr primask, r1 \n\t" \ - : "=r" (LockState) \ - : \ - : "r1" \ - ); - - #define SEGGER_RTT_UNLOCK() __asm volatile ("msr primask, %0 \n\t" \ - : \ - : "r" (LockState) \ - : \ - ); \ - } - - #elif (defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)) - #ifndef SEGGER_RTT_MAX_INTERRUPT_PRIORITY - #define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20) - #endif - #define SEGGER_RTT_LOCK() { \ - unsigned int LockState; \ - __asm volatile ("mrs %0, basepri \n\t" \ - "mov r1, %1 \n\t" \ - "msr basepri, r1 \n\t" \ - : "=r" (LockState) \ - : "i"(SEGGER_RTT_MAX_INTERRUPT_PRIORITY) \ - : "r1" \ - ); - - #define SEGGER_RTT_UNLOCK() __asm volatile ("msr basepri, %0 \n\t" \ - : \ - : "r" (LockState) \ - : \ - ); \ - } - - #elif defined(__ARM_ARCH_7A__) - #define SEGGER_RTT_LOCK() { \ - unsigned int LockState; \ - __asm volatile ("mrs r1, CPSR \n\t" \ - "mov %0, r1 \n\t" \ - "orr r1, r1, #0xC0 \n\t" \ - "msr CPSR_c, r1 \n\t" \ - : "=r" (LockState) \ - : \ - : "r1" \ - ); - - #define SEGGER_RTT_UNLOCK() __asm volatile ("mov r0, %0 \n\t" \ - "mrs r1, CPSR \n\t" \ - "bic r1, r1, #0xC0 \n\t" \ - "and r0, r0, #0xC0 \n\t" \ - "orr r1, r1, r0 \n\t" \ - "msr CPSR_c, r1 \n\t" \ - : \ - : "r" (LockState) \ - : "r0", "r1" \ - ); \ - } -#else - #define SEGGER_RTT_LOCK() - #define SEGGER_RTT_UNLOCK() - #endif -#endif - -/********************************************************************* -* -* RTT lock configuration for IAR EWARM -*/ -#ifdef __ICCARM__ - #if (defined (__ARM6M__) && (__CORE__ == __ARM6M__)) - #define SEGGER_RTT_LOCK() { \ - unsigned int LockState; \ - LockState = __get_PRIMASK(); \ - __set_PRIMASK(1); - - #define SEGGER_RTT_UNLOCK() __set_PRIMASK(LockState); \ - } - #elif ((defined (__ARM7EM__) && (__CORE__ == __ARM7EM__)) || (defined (__ARM7M__) && (__CORE__ == __ARM7M__))) - #ifndef SEGGER_RTT_MAX_INTERRUPT_PRIORITY - #define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20) - #endif - #define SEGGER_RTT_LOCK() { \ - unsigned int LockState; \ - LockState = __get_BASEPRI(); \ - __set_BASEPRI(SEGGER_RTT_MAX_INTERRUPT_PRIORITY); - - #define SEGGER_RTT_UNLOCK() __set_BASEPRI(LockState); \ - } - #endif -#endif - -/********************************************************************* -* -* RTT lock configuration for KEIL ARM -*/ -#ifdef __CC_ARM - #if (defined __TARGET_ARCH_6S_M) - #define SEGGER_RTT_LOCK() { \ - unsigned int LockState; \ - register unsigned char PRIMASK __asm( "primask"); \ - LockState = PRIMASK; \ - PRIMASK = 1u; \ - __schedule_barrier(); - - #define SEGGER_RTT_UNLOCK() PRIMASK = LockState; \ - __schedule_barrier(); \ - } - #elif (defined(__TARGET_ARCH_7_M) || defined(__TARGET_ARCH_7E_M)) - #ifndef SEGGER_RTT_MAX_INTERRUPT_PRIORITY - #define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20) - #endif - #define SEGGER_RTT_LOCK() { \ - unsigned int LockState; \ - register unsigned char BASEPRI __asm( "basepri"); \ - LockState = BASEPRI; \ - BASEPRI = SEGGER_RTT_MAX_INTERRUPT_PRIORITY; \ - __schedule_barrier(); - - #define SEGGER_RTT_UNLOCK() BASEPRI = LockState; \ - __schedule_barrier(); \ - } - #endif -#endif - -/********************************************************************* -* -* RTT lock configuration fallback -*/ -#ifndef SEGGER_RTT_LOCK - #define SEGGER_RTT_LOCK() // Lock RTT (nestable) (i.e. disable interrupts) -#endif - -#ifndef SEGGER_RTT_UNLOCK - #define SEGGER_RTT_UNLOCK() // Unlock RTT (nestable) (i.e. enable previous interrupt lock state) -#endif - -#endif -/*************************** End of file ****************************/ diff --git a/examples/device/nrf52840/segger/SEGGER_RTT_SES.c b/examples/device/nrf52840/segger/SEGGER_RTT_SES.c deleted file mode 100644 index e6634147c..000000000 --- a/examples/device/nrf52840/segger/SEGGER_RTT_SES.c +++ /dev/null @@ -1,76 +0,0 @@ -/********************************************************************* -* SEGGER MICROCONTROLLER GmbH & Co. KG * -* Solutions for real time microcontroller applications * -********************************************************************** -* * -* (c) 2014 - 2015 SEGGER Microcontroller GmbH & Co. KG * -* * -* www.segger.com Support: support@segger.com * -* * -********************************************************************** -* * -* All rights reserved. * -* * -* * This software may in its unmodified form be freely redistributed * -* in source form. * -* * The source code may be modified, provided the source code * -* retains the above copyright notice, this list of conditions and * -* the following disclaimer. * -* * Modified versions of this software in source or linkable form * -* may not be distributed without prior consent of SEGGER. * -* * This software may only be used for communication with SEGGER * -* J-Link debug probes. * -* * -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * -* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * -* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * -* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * -* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR * -* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * -* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * -* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * -* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * -* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * -* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * -* DAMAGE. * -* * -********************************************************************** --------- END-OF-HEADER --------------------------------------------- -File : SEGGER_RTT_Syscalls_SES.c -Purpose : Reimplementation of printf, puts and - implementation of __putchar and __getchar using RTT in SES. - To use RTT for printf output, include this file in your - application. ----------------------------------------------------------------------- -*/ -#include "SEGGER_RTT.h" -#include "__libc.h" -#include -#include - -int printf(const char *fmt,...) { - char buffer[128]; - va_list args; - va_start (args, fmt); - int n = vsnprintf(buffer, sizeof(buffer), fmt, args); - SEGGER_RTT_Write(0, buffer, n); - va_end(args); - return n; -} - -int puts(const char *s) { - return SEGGER_RTT_WriteString(0, s); -} - -int __putchar(int x, __printf_tag_ptr ctx) { - (void)ctx; - SEGGER_RTT_Write(0, (char *)&x, 1); - return x; -} - -int __getchar() { - return SEGGER_RTT_WaitKey(); -} - -/****** End Of File *************************************************/ diff --git a/examples/device/nrf52840/segger/nrf52840.emProject b/examples/device/nrf52840/segger/nrf52840.emProject index 8775d1bca..5851c33d6 100644 --- a/examples/device/nrf52840/segger/nrf52840.emProject +++ b/examples/device/nrf52840/segger/nrf52840.emProject @@ -32,12 +32,6 @@ target_reset_script="Reset();" target_script_file="$(ProjectDir)/nRF_Target.js" target_trace_initialize_script="EnableTrace("$(TraceInterfaceType)")" /> - - - - - - @@ -61,6 +55,12 @@ + + + + + + diff --git a/examples/device/nrf52840/src/main.c b/examples/device/nrf52840/src/main.c index 58ac1ad21..11b73ebf9 100644 --- a/examples/device/nrf52840/src/main.c +++ b/examples/device/nrf52840/src/main.c @@ -55,56 +55,51 @@ //--------------------------------------------------------------------+ void print_greeting(void); void led_blinking_task(void); -void virtual_com_task(void); -void usb_hid_task(void); - -/*------------- MAIN -------------*/ -int main(void) -{ - board_init(); - print_greeting(); - - tusb_init(); - - while (1) - { - tusb_task(); - - led_blinking_task(); - virtual_com_task(); - - usb_hid_task(); - } - - return 0; -} //--------------------------------------------------------------------+ // USB CDC //--------------------------------------------------------------------+ +#if CFG_TUD_CDC void virtual_com_task(void) { -#if CFG_TUD_CDC // connected and there are data available - if ( tud_mounted() && tud_cdc_available() ) + if ( tud_cdc_connected() ) { - uint8_t buf[64]; + if ( tud_cdc_available() ) + { + uint8_t buf[64]; + + // read and echo back + uint32_t count = tud_cdc_read(buf, sizeof(buf)); - // read and echo back - uint32_t count = tud_cdc_read(buf, sizeof(buf)); + tud_cdc_write(buf, count); + } - tud_cdc_write(buf, count); tud_cdc_write_flush(); } -#endif } +void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts) +{ + (void) itf; + + // connected + if ( dtr && rts ) + { + // print greeting + tud_cdc_write_str("tinyusb usb cdc\n"); + } +} +#else +#define virtual_com_task() +#endif + //--------------------------------------------------------------------+ // USB HID //--------------------------------------------------------------------+ +#if CFG_TUD_HID void usb_hid_task(void) { -#if CFG_TUD_HID // Poll every 10ms static tu_timeout_t tm = { .start = 0, .interval = 10 }; @@ -144,10 +139,8 @@ void usb_hid_task(void) if ( btn & 0x04 ) tud_hid_mouse_move( 0 , -DELTA); // up if ( btn & 0x08 ) tud_hid_mouse_move( 0 , DELTA); // down } -#endif } -#if CFG_TUD_HID uint16_t tud_hid_generic_get_report_cb(uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen) { // TODO not Implemented @@ -158,8 +151,32 @@ void tud_hid_generic_set_report_cb(uint8_t report_id, hid_report_type_t report_t { // TODO not Implemented } + +#else +#define usb_hid_task() #endif + +/*------------- MAIN -------------*/ +int main(void) +{ + board_init(); + print_greeting(); + + tusb_init(); + + while (1) + { + tusb_task(); + + led_blinking_task(); + virtual_com_task(); + usb_hid_task(); + } + + return 0; +} + //--------------------------------------------------------------------+ // tinyusb callbacks //--------------------------------------------------------------------+ diff --git a/examples/device/nrf52840/src/segger_rtt/SEGGER_RTT.c b/examples/device/nrf52840/src/segger_rtt/SEGGER_RTT.c new file mode 100644 index 000000000..aee5bd21e --- /dev/null +++ b/examples/device/nrf52840/src/segger_rtt/SEGGER_RTT.c @@ -0,0 +1,1329 @@ +/********************************************************************* +* SEGGER MICROCONTROLLER GmbH & Co. KG * +* Solutions for real time microcontroller applications * +********************************************************************** +* * +* (c) 2014 - 2016 SEGGER Microcontroller GmbH & Co. KG * +* * +* www.segger.com Support: support@segger.com * +* * +********************************************************************** +* * +* SEGGER RTT * Real Time Transfer for embedded targets * +* * +********************************************************************** +* * +* All rights reserved. * +* * +* * This software may in its unmodified form be freely redistributed * +* in source form. * +* * The source code may be modified, provided the source code * +* retains the above copyright notice, this list of conditions and * +* the following disclaimer. * +* * Modified versions of this software in source or linkable form * +* may not be distributed without prior consent of SEGGER. * +* * This software may only be used for communication with SEGGER * +* J-Link debug probes. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * +* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * +* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * +* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * +* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * +* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * +* DAMAGE. * +* * +********************************************************************** +* * +* RTT version: 5.12e * +* * +********************************************************************** +---------------------------END-OF-HEADER------------------------------ +File : SEGGER_RTT.c +Purpose : Implementation of SEGGER real-time transfer (RTT) which + allows real-time communication on targets which support + debugger memory accesses while the CPU is running. + +Additional information: + Type "int" is assumed to be 32-bits in size + H->T Host to target communication + T->H Target to host communication + + RTT channel 0 is always present and reserved for Terminal usage. + Name is fixed to "Terminal" + + Effective buffer size: SizeOfBuffer - 1 + + WrOff == RdOff: Buffer is empty + WrOff == (RdOff - 1): Buffer is full + WrOff > RdOff: Free space includes wrap-around + WrOff < RdOff: Used space includes wrap-around + (WrOff == (SizeOfBuffer - 1)) && (RdOff == 0): + Buffer full and wrap-around after next byte + + +---------------------------------------------------------------------- +*/ + +#include "SEGGER_RTT.h" + +#include // for memcpy + +/********************************************************************* +* +* Configuration, default values +* +********************************************************************** +*/ + +#ifndef BUFFER_SIZE_UP + #define BUFFER_SIZE_UP 1024 // Size of the buffer for terminal output of target, up to host +#endif + +#ifndef BUFFER_SIZE_DOWN + #define BUFFER_SIZE_DOWN 16 // Size of the buffer for terminal input to target from host (Usually keyboard input) +#endif + +#ifndef SEGGER_RTT_MAX_NUM_UP_BUFFERS + #define SEGGER_RTT_MAX_NUM_UP_BUFFERS 2 // Number of up-buffers (T->H) available on this target +#endif + +#ifndef SEGGER_RTT_MAX_NUM_DOWN_BUFFERS + #define SEGGER_RTT_MAX_NUM_DOWN_BUFFERS 2 // Number of down-buffers (H->T) available on this target +#endif + +#ifndef SEGGER_RTT_BUFFER_SECTION + #if defined SEGGER_RTT_SECTION + #define SEGGER_RTT_BUFFER_SECTION SEGGER_RTT_SECTION + #endif +#endif + +#ifndef SEGGER_RTT_MODE_DEFAULT + #define SEGGER_RTT_MODE_DEFAULT SEGGER_RTT_MODE_NO_BLOCK_SKIP +#endif + +#ifndef SEGGER_RTT_LOCK + #define SEGGER_RTT_LOCK() +#endif + +#ifndef SEGGER_RTT_UNLOCK + #define SEGGER_RTT_UNLOCK() +#endif + +#ifndef STRLEN + #define STRLEN(a) strlen((a)) +#endif + +#ifndef MEMCPY + #define MEMCPY(pDest, pSrc, NumBytes) memcpy((pDest), (pSrc), (NumBytes)) +#endif + +#ifndef MIN + #define MIN(a, b) (((a) < (b)) ? (a) : (b)) +#endif + +#ifndef MAX + #define MAX(a, b) (((a) > (b)) ? (a) : (b)) +#endif +// +// For some environments, NULL may not be defined until certain headers are included +// +#ifndef NULL + #define NULL 0 +#endif + +/********************************************************************* +* +* Static const data +* +********************************************************************** +*/ + +static unsigned char _aTerminalId[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; + +/********************************************************************* +* +* Static data +* +********************************************************************** +*/ +// +// RTT Control Block and allocate buffers for channel 0 +// +#ifdef SEGGER_RTT_SECTION + #if (defined __GNUC__) + __attribute__ ((section (SEGGER_RTT_SECTION))) SEGGER_RTT_CB _SEGGER_RTT; + #elif (defined __ICCARM__) || (defined __ICCRX__) + #pragma location=SEGGER_RTT_SECTION + SEGGER_RTT_CB _SEGGER_RTT; + #elif (defined __CC_ARM__) + __attribute__ ((section (SEGGER_RTT_SECTION), zero_init)) SEGGER_RTT_CB _SEGGER_RTT; + #else + SEGGER_RTT_CB _SEGGER_RTT; + #endif +#else + SEGGER_RTT_CB _SEGGER_RTT; +#endif + +#ifdef SEGGER_RTT_BUFFER_SECTION + #if (defined __GNUC__) + __attribute__ ((section (SEGGER_RTT_BUFFER_SECTION))) static char _acUpBuffer [BUFFER_SIZE_UP]; + __attribute__ ((section (SEGGER_RTT_BUFFER_SECTION))) static char _acDownBuffer[BUFFER_SIZE_DOWN]; + #elif (defined __ICCARM__) || (defined __ICCRX__) + #pragma location=SEGGER_RTT_BUFFER_SECTION + static char _acUpBuffer [BUFFER_SIZE_UP]; + #pragma location=SEGGER_RTT_BUFFER_SECTION + static char _acDownBuffer[BUFFER_SIZE_DOWN]; + #elif (defined __CC_ARM__) + __attribute__ ((section (SEGGER_RTT_BUFFER_SECTION), zero_init)) static char _acUpBuffer [BUFFER_SIZE_UP]; + __attribute__ ((section (SEGGER_RTT_BUFFER_SECTION), zero_init)) static char _acDownBuffer[BUFFER_SIZE_DOWN]; + #else + static char _acUpBuffer [BUFFER_SIZE_UP]; + static char _acDownBuffer[BUFFER_SIZE_DOWN]; + #endif +#else + static char _acUpBuffer [BUFFER_SIZE_UP]; + static char _acDownBuffer[BUFFER_SIZE_DOWN]; +#endif + +static char _ActiveTerminal; + +/********************************************************************* +* +* Static functions +* +********************************************************************** +*/ + +/********************************************************************* +* +* _DoInit() +* +* Function description +* Initializes the control block an buffers. +* May only be called via INIT() to avoid overriding settings. +* +*/ +#define INIT() do { \ + if (_SEGGER_RTT.acID[0] == '\0') { _DoInit(); } \ + } while (0) +static void _DoInit(void) { + SEGGER_RTT_CB* p; + // + // Initialize control block + // + p = &_SEGGER_RTT; + p->MaxNumUpBuffers = SEGGER_RTT_MAX_NUM_UP_BUFFERS; + p->MaxNumDownBuffers = SEGGER_RTT_MAX_NUM_DOWN_BUFFERS; + // + // Initialize up buffer 0 + // + p->aUp[0].sName = "Terminal"; + p->aUp[0].pBuffer = _acUpBuffer; + p->aUp[0].SizeOfBuffer = sizeof(_acUpBuffer); + p->aUp[0].RdOff = 0u; + p->aUp[0].WrOff = 0u; + p->aUp[0].Flags = SEGGER_RTT_MODE_DEFAULT; + // + // Initialize down buffer 0 + // + p->aDown[0].sName = "Terminal"; + p->aDown[0].pBuffer = _acDownBuffer; + p->aDown[0].SizeOfBuffer = sizeof(_acDownBuffer); + p->aDown[0].RdOff = 0u; + p->aDown[0].WrOff = 0u; + p->aDown[0].Flags = SEGGER_RTT_MODE_DEFAULT; + // + // Finish initialization of the control block. + // Copy Id string in three steps to make sure "SEGGER RTT" is not found + // in initializer memory (usually flash) by J-Link + // + strcpy(&p->acID[7], "RTT"); + strcpy(&p->acID[0], "SEGGER"); + p->acID[6] = ' '; +} + +/********************************************************************* +* +* _WriteBlocking() +* +* Function description +* Stores a specified number of characters in SEGGER RTT ring buffer +* and updates the associated write pointer which is periodically +* read by the host. +* The caller is responsible for managing the write chunk sizes as +* _WriteBlocking() will block until all data has been posted successfully. +* +* Parameters +* pRing Ring buffer to post to. +* pBuffer Pointer to character array. Does not need to point to a \0 terminated string. +* NumBytes Number of bytes to be stored in the SEGGER RTT control block. +* +* Return value +* >= 0 - Number of bytes written into buffer. +*/ +static unsigned _WriteBlocking(SEGGER_RTT_BUFFER_UP* pRing, const char* pBuffer, unsigned NumBytes) { + unsigned NumBytesToWrite; + unsigned NumBytesWritten; + unsigned RdOff; + unsigned WrOff; + // + // Write data to buffer and handle wrap-around if necessary + // + NumBytesWritten = 0u; + WrOff = pRing->WrOff; + do { + RdOff = pRing->RdOff; // May be changed by host (debug probe) in the meantime + if (RdOff > WrOff) { + NumBytesToWrite = RdOff - WrOff - 1u; + } else { + NumBytesToWrite = pRing->SizeOfBuffer - (WrOff - RdOff + 1u); + } + NumBytesToWrite = MIN(NumBytesToWrite, (pRing->SizeOfBuffer - WrOff)); // Number of bytes that can be written until buffer wrap-around + NumBytesToWrite = MIN(NumBytesToWrite, NumBytes); + memcpy(pRing->pBuffer + WrOff, pBuffer, NumBytesToWrite); + NumBytesWritten += NumBytesToWrite; + pBuffer += NumBytesToWrite; + NumBytes -= NumBytesToWrite; + WrOff += NumBytesToWrite; + if (WrOff == pRing->SizeOfBuffer) { + WrOff = 0u; + } + pRing->WrOff = WrOff; + } while (NumBytes); + // + return NumBytesWritten; +} + +/********************************************************************* +* +* _WriteNoCheck() +* +* Function description +* Stores a specified number of characters in SEGGER RTT ring buffer +* and updates the associated write pointer which is periodically +* read by the host. +* It is callers responsibility to make sure data actually fits in buffer. +* +* Parameters +* pRing Ring buffer to post to. +* pBuffer Pointer to character array. Does not need to point to a \0 terminated string. +* NumBytes Number of bytes to be stored in the SEGGER RTT control block. +* +* Notes +* (1) If there might not be enough space in the "Up"-buffer, call _WriteBlocking +*/ +static void _WriteNoCheck(SEGGER_RTT_BUFFER_UP* pRing, const char* pData, unsigned NumBytes) { + unsigned NumBytesAtOnce; + unsigned WrOff; + unsigned Rem; + + WrOff = pRing->WrOff; + Rem = pRing->SizeOfBuffer - WrOff; + if (Rem > NumBytes) { + // + // All data fits before wrap around + // + memcpy(pRing->pBuffer + WrOff, pData, NumBytes); + pRing->WrOff = WrOff + NumBytes; + } else { + // + // We reach the end of the buffer, so need to wrap around + // + NumBytesAtOnce = Rem; + memcpy(pRing->pBuffer + WrOff, pData, NumBytesAtOnce); + NumBytesAtOnce = NumBytes - Rem; + memcpy(pRing->pBuffer, pData + Rem, NumBytesAtOnce); + pRing->WrOff = NumBytesAtOnce; + } +} + +/********************************************************************* +* +* _PostTerminalSwitch() +* +* Function description +* Switch terminal to the given terminal ID. It is the caller's +* responsibility to ensure the terminal ID is correct and there is +* enough space in the buffer for this to complete successfully. +* +* Parameters +* pRing Ring buffer to post to. +* TerminalId Terminal ID to switch to. +*/ +static void _PostTerminalSwitch(SEGGER_RTT_BUFFER_UP* pRing, unsigned char TerminalId) { + char ac[2]; + + ac[0] = 0xFFu; + ac[1] = _aTerminalId[TerminalId]; // Caller made already sure that TerminalId does not exceed our terminal limit + _WriteBlocking(pRing, ac, 2u); +} + +/********************************************************************* +* +* _GetAvailWriteSpace() +* +* Function description +* Returns the number of bytes that can be written to the ring +* buffer without blocking. +* +* Parameters +* pRing Ring buffer to check. +* +* Return value +* Number of bytes that are free in the buffer. +*/ +static unsigned _GetAvailWriteSpace(SEGGER_RTT_BUFFER_UP* pRing) { + unsigned RdOff; + unsigned WrOff; + unsigned r; + // + // Avoid warnings regarding volatile access order. It's not a problem + // in this case, but dampen compiler enthusiasm. + // + RdOff = pRing->RdOff; + WrOff = pRing->WrOff; + if (RdOff <= WrOff) { + r = pRing->SizeOfBuffer - 1u - WrOff + RdOff; + } else { + r = RdOff - WrOff - 1u; + } + return r; +} + +/********************************************************************* +* +* Public code +* +********************************************************************** +*/ +/********************************************************************* +* +* SEGGER_RTT_ReadNoLock() +* +* Function description +* Reads characters from SEGGER real-time-terminal control block +* which have been previously stored by the host. +* Do not lock against interrupts and multiple access. +* +* Parameters +* BufferIndex Index of Down-buffer to be used (e.g. 0 for "Terminal"). +* pBuffer Pointer to buffer provided by target application, to copy characters from RTT-down-buffer to. +* BufferSize Size of the target application buffer. +* +* Return value +* Number of bytes that have been read. +*/ +unsigned SEGGER_RTT_ReadNoLock(unsigned BufferIndex, void* pData, unsigned BufferSize) { + unsigned NumBytesRem; + unsigned NumBytesRead; + unsigned RdOff; + unsigned WrOff; + unsigned char* pBuffer; + SEGGER_RTT_BUFFER_DOWN* pRing; + // + INIT(); + pRing = &_SEGGER_RTT.aDown[BufferIndex]; + pBuffer = (unsigned char*)pData; + RdOff = pRing->RdOff; + WrOff = pRing->WrOff; + NumBytesRead = 0u; + // + // Read from current read position to wrap-around of buffer, first + // + if (RdOff > WrOff) { + NumBytesRem = pRing->SizeOfBuffer - RdOff; + NumBytesRem = MIN(NumBytesRem, BufferSize); + memcpy(pBuffer, pRing->pBuffer + RdOff, NumBytesRem); + NumBytesRead += NumBytesRem; + pBuffer += NumBytesRem; + BufferSize -= NumBytesRem; + RdOff += NumBytesRem; + // + // Handle wrap-around of buffer + // + if (RdOff == pRing->SizeOfBuffer) { + RdOff = 0u; + } + } + // + // Read remaining items of buffer + // + NumBytesRem = WrOff - RdOff; + NumBytesRem = MIN(NumBytesRem, BufferSize); + if (NumBytesRem > 0u) { + memcpy(pBuffer, pRing->pBuffer + RdOff, NumBytesRem); + NumBytesRead += NumBytesRem; + pBuffer += NumBytesRem; + BufferSize -= NumBytesRem; + RdOff += NumBytesRem; + } + if (NumBytesRead) { + pRing->RdOff = RdOff; + } + // + return NumBytesRead; +} + +/********************************************************************* +* +* SEGGER_RTT_Read +* +* Function description +* Reads characters from SEGGER real-time-terminal control block +* which have been previously stored by the host. +* +* Parameters +* BufferIndex Index of Down-buffer to be used (e.g. 0 for "Terminal"). +* pBuffer Pointer to buffer provided by target application, to copy characters from RTT-down-buffer to. +* BufferSize Size of the target application buffer. +* +* Return value +* Number of bytes that have been read. +*/ +unsigned SEGGER_RTT_Read(unsigned BufferIndex, void* pBuffer, unsigned BufferSize) { + unsigned NumBytesRead; + // + SEGGER_RTT_LOCK(); + // + // Call the non-locking read function + // + NumBytesRead = SEGGER_RTT_ReadNoLock(BufferIndex, pBuffer, BufferSize); + // + // Finish up. + // + SEGGER_RTT_UNLOCK(); + // + return NumBytesRead; +} + +/********************************************************************* +* +* SEGGER_RTT_WriteWithOverwriteNoLock +* +* Function description +* Stores a specified number of characters in SEGGER RTT +* control block. +* SEGGER_RTT_WriteWithOverwriteNoLock does not lock the application +* and overwrites data if the data does not fit into the buffer. +* +* Parameters +* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). +* pBuffer Pointer to character array. Does not need to point to a \0 terminated string. +* NumBytes Number of bytes to be stored in the SEGGER RTT control block. +* +* Notes +* (1) If there is not enough space in the "Up"-buffer, data is overwritten. +* (2) For performance reasons this function does not call Init() +* and may only be called after RTT has been initialized. +* Either by calling SEGGER_RTT_Init() or calling another RTT API function first. +* (3) Do not use SEGGER_RTT_WriteWithOverwriteNoLock if a J-Link +* connection reads RTT data. +*/ +void SEGGER_RTT_WriteWithOverwriteNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) { + const char* pData; + SEGGER_RTT_BUFFER_UP* pRing; + unsigned Avail; + + pData = (const char *)pBuffer; + // + // Get "to-host" ring buffer and copy some elements into local variables. + // + pRing = &_SEGGER_RTT.aUp[BufferIndex]; + // + // Check if we will overwrite data and need to adjust the RdOff. + // + if (pRing->WrOff == pRing->RdOff) { + Avail = pRing->SizeOfBuffer - 1u; + } else if ( pRing->WrOff < pRing->RdOff) { + Avail = pRing->RdOff - pRing->WrOff - 1u; + } else { + Avail = pRing->RdOff - pRing->WrOff - 1u + pRing->SizeOfBuffer; + } + if (NumBytes > Avail) { + pRing->RdOff += (NumBytes - Avail); + while (pRing->RdOff >= pRing->SizeOfBuffer) { + pRing->RdOff -= pRing->SizeOfBuffer; + } + } + // + // Write all data, no need to check the RdOff, but possibly handle multiple wrap-arounds + // + Avail = pRing->SizeOfBuffer - pRing->WrOff; + do { + if (Avail > NumBytes) { + // + // Last round + // +#if 1 // memcpy() is good for large amounts of data, but the overhead is too big for small amounts. Use a simple byte loop instead. + char* pDst; + pDst = pRing->pBuffer + pRing->WrOff; + pRing->WrOff += NumBytes; + do { + *pDst++ = *pData++; + } while (--NumBytes); +#else + memcpy(pRing->pBuffer + WrOff, pData, NumBytes); + pRing->WrOff += NumBytes; +#endif + break; //Alternatively: NumBytes = 0; + } else { + // + // Wrap-around necessary, write until wrap-around and reset WrOff + // + memcpy(pRing->pBuffer + pRing->WrOff, pData, Avail); + pData += Avail; + pRing->WrOff = 0; + NumBytes -= Avail; + Avail = (pRing->SizeOfBuffer - 1); + } + } while (NumBytes); +} + +/********************************************************************* +* +* SEGGER_RTT_WriteSkipNoLock +* +* Function description +* Stores a specified number of characters in SEGGER RTT +* control block which is then read by the host. +* SEGGER_RTT_WriteSkipNoLock does not lock the application and +* skips all data, if the data does not fit into the buffer. +* +* Parameters +* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). +* pBuffer Pointer to character array. Does not need to point to a \0 terminated string. +* NumBytes Number of bytes to be stored in the SEGGER RTT control block. +* +* Return value +* Number of bytes which have been stored in the "Up"-buffer. +* +* Notes +* (1) If there is not enough space in the "Up"-buffer, all data is dropped. +* (2) For performance reasons this function does not call Init() +* and may only be called after RTT has been initialized. +* Either by calling SEGGER_RTT_Init() or calling another RTT API function first. +*/ +unsigned SEGGER_RTT_WriteSkipNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) { + const char* pData; + SEGGER_RTT_BUFFER_UP* pRing; + unsigned Avail; + unsigned RdOff; + unsigned WrOff; + unsigned Rem; + + pData = (const char *)pBuffer; + // + // Get "to-host" ring buffer and copy some elements into local variables. + // + pRing = &_SEGGER_RTT.aUp[BufferIndex]; + RdOff = pRing->RdOff; + WrOff = pRing->WrOff; + // + // Handle the most common cases fastest. + // Which is: + // RdOff <= WrOff -> Space until wrap around is free. + // AND + // WrOff + NumBytes < SizeOfBuffer -> No Wrap around necessary. + // + // OR + // + // RdOff > WrOff -> Space until RdOff - 1 is free. + // AND + // WrOff + NumBytes < RdOff -> Data fits into buffer + // + if (RdOff <= WrOff) { + // + // Get space until WrOff will be at wrap around. + // + Avail = pRing->SizeOfBuffer - 1u - WrOff ; + if (Avail >= NumBytes) { +#if 1 // memcpy() is good for large amounts of data, but the overhead is too big for small amounts. Use a simple byte loop instead. + char* pDst; + pDst = pRing->pBuffer + WrOff; + WrOff += NumBytes; + do { + *pDst++ = *pData++; + } while (--NumBytes); + pRing->WrOff = WrOff + NumBytes; +#else + memcpy(pRing->pBuffer + WrOff, pData, NumBytes); + pRing->WrOff = WrOff + NumBytes; +#endif + return 1; + } + // + // If data did not fit into space until wrap around calculate complete space in buffer. + // + Avail += RdOff; + // + // If there is still no space for the whole of this output, don't bother. + // + if (Avail >= NumBytes) { + // + // OK, we have enough space in buffer. Copy in one or 2 chunks + // + Rem = pRing->SizeOfBuffer - WrOff; // Space until end of buffer + if (Rem > NumBytes) { + memcpy(pRing->pBuffer + WrOff, pData, NumBytes); + pRing->WrOff = WrOff + NumBytes; + } else { + // + // We reach the end of the buffer, so need to wrap around + // + memcpy(pRing->pBuffer + WrOff, pData, Rem); + memcpy(pRing->pBuffer, pData + Rem, NumBytes - Rem); + pRing->WrOff = NumBytes - Rem; + } + return 1; + } + } else { + Avail = RdOff - WrOff - 1u; + if (Avail >= NumBytes) { + memcpy(pRing->pBuffer + WrOff, pData, NumBytes); + pRing->WrOff = WrOff + NumBytes; + return 1; + } + } + // + // If we reach this point no data has been written + // + return 0; +} + +/********************************************************************* +* +* SEGGER_RTT_WriteNoLock +* +* Function description +* Stores a specified number of characters in SEGGER RTT +* control block which is then read by the host. +* SEGGER_RTT_WriteNoLock does not lock the application. +* +* Parameters +* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). +* pBuffer Pointer to character array. Does not need to point to a \0 terminated string. +* NumBytes Number of bytes to be stored in the SEGGER RTT control block. +* +* Return value +* Number of bytes which have been stored in the "Up"-buffer. +* +* Notes +* (1) If there is not enough space in the "Up"-buffer, remaining characters of pBuffer are dropped. +* (2) For performance reasons this function does not call Init() +* and may only be called after RTT has been initialized. +* Either by calling SEGGER_RTT_Init() or calling another RTT API function first. +*/ +unsigned SEGGER_RTT_WriteNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) { + unsigned Status; + unsigned Avail; + const char* pData; + SEGGER_RTT_BUFFER_UP* pRing; + + pData = (const char *)pBuffer; + // + // Get "to-host" ring buffer. + // + pRing = &_SEGGER_RTT.aUp[BufferIndex]; + // + // How we output depends upon the mode... + // + switch (pRing->Flags) { + case SEGGER_RTT_MODE_NO_BLOCK_SKIP: + // + // If we are in skip mode and there is no space for the whole + // of this output, don't bother. + // + Avail = _GetAvailWriteSpace(pRing); + if (Avail < NumBytes) { + Status = 0u; + } else { + Status = NumBytes; + _WriteNoCheck(pRing, pData, NumBytes); + } + break; + case SEGGER_RTT_MODE_NO_BLOCK_TRIM: + // + // If we are in trim mode, trim to what we can output without blocking. + // + Avail = _GetAvailWriteSpace(pRing); + Status = Avail < NumBytes ? Avail : NumBytes; + _WriteNoCheck(pRing, pData, Status); + break; + case SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL: + // + // If we are in blocking mode, output everything. + // + Status = _WriteBlocking(pRing, pData, NumBytes); + break; + default: + Status = 0u; + break; + } + // + // Finish up. + // + return Status; +} + +/********************************************************************* +* +* SEGGER_RTT_Write +* +* Function description +* Stores a specified number of characters in SEGGER RTT +* control block which is then read by the host. +* +* Parameters +* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). +* pBuffer Pointer to character array. Does not need to point to a \0 terminated string. +* NumBytes Number of bytes to be stored in the SEGGER RTT control block. +* +* Return value +* Number of bytes which have been stored in the "Up"-buffer. +* +* Notes +* (1) If there is not enough space in the "Up"-buffer, remaining characters of pBuffer are dropped. +*/ +unsigned SEGGER_RTT_Write(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) { + unsigned Status; + // + INIT(); + SEGGER_RTT_LOCK(); + // + // Call the non-locking write function + // + Status = SEGGER_RTT_WriteNoLock(BufferIndex, pBuffer, NumBytes); + // + // Finish up. + // + SEGGER_RTT_UNLOCK(); + // + return Status; +} + +/********************************************************************* +* +* SEGGER_RTT_WriteString +* +* Function description +* Stores string in SEGGER RTT control block. +* This data is read by the host. +* +* Parameters +* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). +* s Pointer to string. +* +* Return value +* Number of bytes which have been stored in the "Up"-buffer. +* +* Notes +* (1) If there is not enough space in the "Up"-buffer, depending on configuration, +* remaining characters may be dropped or RTT module waits until there is more space in the buffer. +* (2) String passed to this function has to be \0 terminated +* (3) \0 termination character is *not* stored in RTT buffer +*/ +unsigned SEGGER_RTT_WriteString(unsigned BufferIndex, const char* s) { + unsigned Len; + + Len = STRLEN(s); + return SEGGER_RTT_Write(BufferIndex, s, Len); +} + +/********************************************************************* +* +* SEGGER_RTT_GetKey +* +* Function description +* Reads one character from the SEGGER RTT buffer. +* Host has previously stored data there. +* +* Return value +* < 0 - No character available (buffer empty). +* >= 0 - Character which has been read. (Possible values: 0 - 255) +* +* Notes +* (1) This function is only specified for accesses to RTT buffer 0. +*/ +int SEGGER_RTT_GetKey(void) { + char c; + int r; + + r = (int)SEGGER_RTT_Read(0u, &c, 1u); + if (r == 1) { + r = (int)(unsigned char)c; + } else { + r = -1; + } + return r; +} + +/********************************************************************* +* +* SEGGER_RTT_WaitKey +* +* Function description +* Waits until at least one character is avaible in the SEGGER RTT buffer. +* Once a character is available, it is read and this function returns. +* +* Return value +* >=0 - Character which has been read. +* +* Notes +* (1) This function is only specified for accesses to RTT buffer 0 +* (2) This function is blocking if no character is present in RTT buffer +*/ +int SEGGER_RTT_WaitKey(void) { + int r; + + do { + r = SEGGER_RTT_GetKey(); + } while (r < 0); + return r; +} + +/********************************************************************* +* +* SEGGER_RTT_HasKey +* +* Function description +* Checks if at least one character for reading is available in the SEGGER RTT buffer. +* +* Return value +* == 0 - No characters are available to read. +* == 1 - At least one character is available. +* +* Notes +* (1) This function is only specified for accesses to RTT buffer 0 +*/ +int SEGGER_RTT_HasKey(void) { + unsigned RdOff; + int r; + + INIT(); + RdOff = _SEGGER_RTT.aDown[0].RdOff; + if (RdOff != _SEGGER_RTT.aDown[0].WrOff) { + r = 1; + } else { + r = 0; + } + return r; +} + +/********************************************************************* +* +* SEGGER_RTT_HasData +* +* Function description +* Check if there is data from the host in the given buffer. +* +* Return value: +* ==0: No data +* !=0: Data in buffer +* +*/ +unsigned SEGGER_RTT_HasData(unsigned BufferIndex) { + SEGGER_RTT_BUFFER_DOWN* pRing; + unsigned v; + + pRing = &_SEGGER_RTT.aDown[BufferIndex]; + v = pRing->WrOff; + return v - pRing->RdOff; +} + +/********************************************************************* +* +* SEGGER_RTT_AllocDownBuffer +* +* Function description +* Run-time configuration of the next down-buffer (H->T). +* The next buffer, which is not used yet is configured. +* This includes: Buffer address, size, name, flags, ... +* +* Parameters +* sName Pointer to a constant name string. +* pBuffer Pointer to a buffer to be used. +* BufferSize Size of the buffer. +* Flags Operating modes. Define behavior if buffer is full (not enough space for entire message). +* +* Return value +* >= 0 - O.K. Buffer Index +* < 0 - Error +*/ +int SEGGER_RTT_AllocDownBuffer(const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) { + int BufferIndex; + + INIT(); + SEGGER_RTT_LOCK(); + BufferIndex = 0; + do { + if (_SEGGER_RTT.aDown[BufferIndex].pBuffer == NULL) { + break; + } + BufferIndex++; + } while (BufferIndex < _SEGGER_RTT.MaxNumDownBuffers); + if (BufferIndex < _SEGGER_RTT.MaxNumDownBuffers) { + _SEGGER_RTT.aDown[BufferIndex].sName = sName; + _SEGGER_RTT.aDown[BufferIndex].pBuffer = pBuffer; + _SEGGER_RTT.aDown[BufferIndex].SizeOfBuffer = BufferSize; + _SEGGER_RTT.aDown[BufferIndex].RdOff = 0u; + _SEGGER_RTT.aDown[BufferIndex].WrOff = 0u; + _SEGGER_RTT.aDown[BufferIndex].Flags = Flags; + } else { + BufferIndex = -1; + } + SEGGER_RTT_UNLOCK(); + return BufferIndex; +} + +/********************************************************************* +* +* SEGGER_RTT_AllocUpBuffer +* +* Function description +* Run-time configuration of the next up-buffer (T->H). +* The next buffer, which is not used yet is configured. +* This includes: Buffer address, size, name, flags, ... +* +* Parameters +* sName Pointer to a constant name string. +* pBuffer Pointer to a buffer to be used. +* BufferSize Size of the buffer. +* Flags Operating modes. Define behavior if buffer is full (not enough space for entire message). +* +* Return value +* >= 0 - O.K. Buffer Index +* < 0 - Error +*/ +int SEGGER_RTT_AllocUpBuffer(const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) { + int BufferIndex; + + INIT(); + SEGGER_RTT_LOCK(); + BufferIndex = 0; + do { + if (_SEGGER_RTT.aUp[BufferIndex].pBuffer == NULL) { + break; + } + BufferIndex++; + } while (BufferIndex < _SEGGER_RTT.MaxNumUpBuffers); + if (BufferIndex < _SEGGER_RTT.MaxNumUpBuffers) { + _SEGGER_RTT.aUp[BufferIndex].sName = sName; + _SEGGER_RTT.aUp[BufferIndex].pBuffer = pBuffer; + _SEGGER_RTT.aUp[BufferIndex].SizeOfBuffer = BufferSize; + _SEGGER_RTT.aUp[BufferIndex].RdOff = 0u; + _SEGGER_RTT.aUp[BufferIndex].WrOff = 0u; + _SEGGER_RTT.aUp[BufferIndex].Flags = Flags; + } else { + BufferIndex = -1; + } + SEGGER_RTT_UNLOCK(); + return BufferIndex; +} + +/********************************************************************* +* +* SEGGER_RTT_ConfigUpBuffer +* +* Function description +* Run-time configuration of a specific up-buffer (T->H). +* Buffer to be configured is specified by index. +* This includes: Buffer address, size, name, flags, ... +* +* Parameters +* BufferIndex Index of the buffer to configure. +* sName Pointer to a constant name string. +* pBuffer Pointer to a buffer to be used. +* BufferSize Size of the buffer. +* Flags Operating modes. Define behavior if buffer is full (not enough space for entire message). +* +* Return value +* >= 0 - O.K. +* < 0 - Error +*/ +int SEGGER_RTT_ConfigUpBuffer(unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) { + int r; + + INIT(); + if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumUpBuffers) { + SEGGER_RTT_LOCK(); + if (BufferIndex > 0u) { + _SEGGER_RTT.aUp[BufferIndex].sName = sName; + _SEGGER_RTT.aUp[BufferIndex].pBuffer = pBuffer; + _SEGGER_RTT.aUp[BufferIndex].SizeOfBuffer = BufferSize; + _SEGGER_RTT.aUp[BufferIndex].RdOff = 0u; + _SEGGER_RTT.aUp[BufferIndex].WrOff = 0u; + } + _SEGGER_RTT.aUp[BufferIndex].Flags = Flags; + SEGGER_RTT_UNLOCK(); + r = 0; + } else { + r = -1; + } + return r; +} + +/********************************************************************* +* +* SEGGER_RTT_ConfigDownBuffer +* +* Function description +* Run-time configuration of a specific down-buffer (H->T). +* Buffer to be configured is specified by index. +* This includes: Buffer address, size, name, flags, ... +* +* Parameters +* BufferIndex Index of the buffer to configure. +* sName Pointer to a constant name string. +* pBuffer Pointer to a buffer to be used. +* BufferSize Size of the buffer. +* Flags Operating modes. Define behavior if buffer is full (not enough space for entire message). +* +* Return value +* >= 0 O.K. +* < 0 Error +*/ +int SEGGER_RTT_ConfigDownBuffer(unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) { + int r; + + INIT(); + if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumDownBuffers) { + SEGGER_RTT_LOCK(); + if (BufferIndex > 0u) { + _SEGGER_RTT.aDown[BufferIndex].sName = sName; + _SEGGER_RTT.aDown[BufferIndex].pBuffer = pBuffer; + _SEGGER_RTT.aDown[BufferIndex].SizeOfBuffer = BufferSize; + _SEGGER_RTT.aDown[BufferIndex].RdOff = 0u; + _SEGGER_RTT.aDown[BufferIndex].WrOff = 0u; + } + _SEGGER_RTT.aDown[BufferIndex].Flags = Flags; + SEGGER_RTT_UNLOCK(); + r = 0; + } else { + r = -1; + } + return r; +} + +/********************************************************************* +* +* SEGGER_RTT_SetNameUpBuffer +* +* Function description +* Run-time configuration of a specific up-buffer name (T->H). +* Buffer to be configured is specified by index. +* +* Parameters +* BufferIndex Index of the buffer to renamed. +* sName Pointer to a constant name string. +* +* Return value +* >= 0 O.K. +* < 0 Error +*/ +int SEGGER_RTT_SetNameUpBuffer(unsigned BufferIndex, const char* sName) { + int r; + + INIT(); + if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumUpBuffers) { + SEGGER_RTT_LOCK(); + _SEGGER_RTT.aUp[BufferIndex].sName = sName; + SEGGER_RTT_UNLOCK(); + r = 0; + } else { + r = -1; + } + return r; +} + +/********************************************************************* +* +* SEGGER_RTT_SetNameDownBuffer +* +* Function description +* Run-time configuration of a specific Down-buffer name (T->H). +* Buffer to be configured is specified by index. +* +* Parameters +* BufferIndex Index of the buffer to renamed. +* sName Pointer to a constant name string. +* +* Return value +* >= 0 O.K. +* < 0 Error +*/ +int SEGGER_RTT_SetNameDownBuffer(unsigned BufferIndex, const char* sName) { + int r; + + INIT(); + if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumDownBuffers) { + SEGGER_RTT_LOCK(); + _SEGGER_RTT.aDown[BufferIndex].sName = sName; + SEGGER_RTT_UNLOCK(); + r = 0; + } else { + r = -1; + } + return r; +} + +/********************************************************************* +* +* SEGGER_RTT_Init +* +* Function description +* Initializes the RTT Control Block. +* Should be used in RAM targets, at start of the application. +* +*/ +void SEGGER_RTT_Init (void) { + _DoInit(); +} + +/********************************************************************* +* +* SEGGER_RTT_SetTerminal +* +* Function description +* Sets the terminal to be used for output on channel 0. +* +* Parameters +* TerminalId Index of the terminal. +* +* Return value +* >= 0 O.K. +* < 0 Error (e.g. if RTT is configured for non-blocking mode and there was no space in the buffer to set the new terminal Id) +*/ +int SEGGER_RTT_SetTerminal (char TerminalId) { + char ac[2]; + SEGGER_RTT_BUFFER_UP* pRing; + unsigned Avail; + int r; + // + INIT(); + // + r = 0; + ac[0] = 0xFFU; + if ((unsigned char)TerminalId < (unsigned char)sizeof(_aTerminalId)) { // We only support a certain number of channels + ac[1] = _aTerminalId[(unsigned char)TerminalId]; + pRing = &_SEGGER_RTT.aUp[0]; // Buffer 0 is always reserved for terminal I/O, so we can use index 0 here, fixed + SEGGER_RTT_LOCK(); // Lock to make sure that no other task is writing into buffer, while we are and number of free bytes in buffer does not change downwards after checking and before writing + if ((pRing->Flags & SEGGER_RTT_MODE_MASK) == SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL) { + _ActiveTerminal = TerminalId; + _WriteBlocking(pRing, ac, 2u); + } else { // Skipping mode or trim mode? => We cannot trim this command so handling is the same for both modes + Avail = _GetAvailWriteSpace(pRing); + if (Avail >= 2) { + _ActiveTerminal = TerminalId; // Only change active terminal in case of success + _WriteNoCheck(pRing, ac, 2u); + } else { + r = -1; + } + } + SEGGER_RTT_UNLOCK(); + } else { + r = -1; + } + return r; +} + +/********************************************************************* +* +* SEGGER_RTT_TerminalOut +* +* Function description +* Writes a string to the given terminal +* without changing the terminal for channel 0. +* +* Parameters +* TerminalId Index of the terminal. +* s String to be printed on the terminal. +* +* Return value +* >= 0 - Number of bytes written. +* < 0 - Error. +* +*/ +int SEGGER_RTT_TerminalOut (char TerminalId, const char* s) { + int Status; + unsigned FragLen; + unsigned Avail; + SEGGER_RTT_BUFFER_UP* pRing; + // + INIT(); + // + // Validate terminal ID. + // + if (TerminalId < (char)sizeof(_aTerminalId)) { // We only support a certain number of channels + // + // Get "to-host" ring buffer. + // + pRing = &_SEGGER_RTT.aUp[0]; + // + // Need to be able to change terminal, write data, change back. + // Compute the fixed and variable sizes. + // + FragLen = strlen(s); + // + // How we output depends upon the mode... + // + SEGGER_RTT_LOCK(); + Avail = _GetAvailWriteSpace(pRing); + switch (pRing->Flags & SEGGER_RTT_MODE_MASK) { + case SEGGER_RTT_MODE_NO_BLOCK_SKIP: + // + // If we are in skip mode and there is no space for the whole + // of this output, don't bother switching terminals at all. + // + if (Avail < (FragLen + 4u)) { + Status = 0; + } else { + _PostTerminalSwitch(pRing, TerminalId); + Status = (int)_WriteBlocking(pRing, s, FragLen); + _PostTerminalSwitch(pRing, _ActiveTerminal); + } + break; + case SEGGER_RTT_MODE_NO_BLOCK_TRIM: + // + // If we are in trim mode and there is not enough space for everything, + // trim the output but always include the terminal switch. If no room + // for terminal switch, skip that totally. + // + if (Avail < 4u) { + Status = -1; + } else { + _PostTerminalSwitch(pRing, TerminalId); + Status = (int)_WriteBlocking(pRing, s, (FragLen < (Avail - 4u)) ? FragLen : (Avail - 4u)); + _PostTerminalSwitch(pRing, _ActiveTerminal); + } + break; + case SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL: + // + // If we are in blocking mode, output everything. + // + _PostTerminalSwitch(pRing, TerminalId); + Status = (int)_WriteBlocking(pRing, s, FragLen); + _PostTerminalSwitch(pRing, _ActiveTerminal); + break; + default: + Status = -1; + break; + } + // + // Finish up. + // + SEGGER_RTT_UNLOCK(); + } else { + Status = -1; + } + return Status; +} + + +/*************************** End of file ****************************/ diff --git a/examples/device/nrf52840/src/segger_rtt/SEGGER_RTT.h b/examples/device/nrf52840/src/segger_rtt/SEGGER_RTT.h new file mode 100644 index 000000000..d3cac44dd --- /dev/null +++ b/examples/device/nrf52840/src/segger_rtt/SEGGER_RTT.h @@ -0,0 +1,234 @@ +/********************************************************************* +* SEGGER MICROCONTROLLER GmbH & Co. KG * +* Solutions for real time microcontroller applications * +********************************************************************** +* * +* (c) 2014 - 2016 SEGGER Microcontroller GmbH & Co. KG * +* * +* www.segger.com Support: support@segger.com * +* * +********************************************************************** +* * +* SEGGER RTT * Real Time Transfer for embedded targets * +* * +********************************************************************** +* * +* All rights reserved. * +* * +* * This software may in its unmodified form be freely redistributed * +* in source form. * +* * The source code may be modified, provided the source code * +* retains the above copyright notice, this list of conditions and * +* the following disclaimer. * +* * Modified versions of this software in source or linkable form * +* may not be distributed without prior consent of SEGGER. * +* * This software may only be used for communication with SEGGER * +* J-Link debug probes. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * +* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * +* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * +* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * +* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * +* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * +* DAMAGE. * +* * +********************************************************************** +* * +* RTT version: 5.12e * +* * +********************************************************************** +---------------------------END-OF-HEADER------------------------------ +File : SEGGER_RTT.h +Purpose : Implementation of SEGGER real-time transfer which allows + real-time communication on targets which support debugger + memory accesses while the CPU is running. +---------------------------------------------------------------------- +*/ + +#ifndef SEGGER_RTT_H +#define SEGGER_RTT_H + +#include "SEGGER_RTT_Conf.h" + +/********************************************************************* +* +* Defines, fixed +* +********************************************************************** +*/ + +/********************************************************************* +* +* Types +* +********************************************************************** +*/ + +// +// Description for a circular buffer (also called "ring buffer") +// which is used as up-buffer (T->H) +// +typedef struct { + const char* sName; // Optional name. Standard names so far are: "Terminal", "SysView", "J-Scope_t4i4" + char* pBuffer; // Pointer to start of buffer + unsigned SizeOfBuffer; // Buffer size in bytes. Note that one byte is lost, as this implementation does not fill up the buffer in order to avoid the problem of being unable to distinguish between full and empty. + unsigned WrOff; // Position of next item to be written by either target. + volatile unsigned RdOff; // Position of next item to be read by host. Must be volatile since it may be modified by host. + unsigned Flags; // Contains configuration flags +} SEGGER_RTT_BUFFER_UP; + +// +// Description for a circular buffer (also called "ring buffer") +// which is used as down-buffer (H->T) +// +typedef struct { + const char* sName; // Optional name. Standard names so far are: "Terminal", "SysView", "J-Scope_t4i4" + char* pBuffer; // Pointer to start of buffer + unsigned SizeOfBuffer; // Buffer size in bytes. Note that one byte is lost, as this implementation does not fill up the buffer in order to avoid the problem of being unable to distinguish between full and empty. + volatile unsigned WrOff; // Position of next item to be written by host. Must be volatile since it may be modified by host. + unsigned RdOff; // Position of next item to be read by target (down-buffer). + unsigned Flags; // Contains configuration flags +} SEGGER_RTT_BUFFER_DOWN; + +// +// RTT control block which describes the number of buffers available +// as well as the configuration for each buffer +// +// +typedef struct { + char acID[16]; // Initialized to "SEGGER RTT" + int MaxNumUpBuffers; // Initialized to SEGGER_RTT_MAX_NUM_UP_BUFFERS (type. 2) + int MaxNumDownBuffers; // Initialized to SEGGER_RTT_MAX_NUM_DOWN_BUFFERS (type. 2) + SEGGER_RTT_BUFFER_UP aUp[SEGGER_RTT_MAX_NUM_UP_BUFFERS]; // Up buffers, transferring information up from target via debug probe to host + SEGGER_RTT_BUFFER_DOWN aDown[SEGGER_RTT_MAX_NUM_DOWN_BUFFERS]; // Down buffers, transferring information down from host via debug probe to target +} SEGGER_RTT_CB; + +/********************************************************************* +* +* Global data +* +********************************************************************** +*/ +extern SEGGER_RTT_CB _SEGGER_RTT; + +/********************************************************************* +* +* RTT API functions +* +********************************************************************** +*/ +#ifdef __cplusplus + extern "C" { +#endif +int SEGGER_RTT_AllocDownBuffer (const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags); +int SEGGER_RTT_AllocUpBuffer (const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags); +int SEGGER_RTT_ConfigUpBuffer (unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags); +int SEGGER_RTT_ConfigDownBuffer (unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags); +int SEGGER_RTT_GetKey (void); +unsigned SEGGER_RTT_HasData (unsigned BufferIndex); +int SEGGER_RTT_HasKey (void); +void SEGGER_RTT_Init (void); +unsigned SEGGER_RTT_Read (unsigned BufferIndex, void* pBuffer, unsigned BufferSize); +unsigned SEGGER_RTT_ReadNoLock (unsigned BufferIndex, void* pData, unsigned BufferSize); +int SEGGER_RTT_SetNameDownBuffer(unsigned BufferIndex, const char* sName); +int SEGGER_RTT_SetNameUpBuffer (unsigned BufferIndex, const char* sName); +int SEGGER_RTT_WaitKey (void); +unsigned SEGGER_RTT_Write (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes); +unsigned SEGGER_RTT_WriteNoLock (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes); +unsigned SEGGER_RTT_WriteSkipNoLock (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes); +unsigned SEGGER_RTT_WriteString (unsigned BufferIndex, const char* s); +void SEGGER_RTT_WriteWithOverwriteNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes); +// +// Function macro for performance optimization +// +#define SEGGER_RTT_HASDATA(n) (_SEGGER_RTT.aDown[n].WrOff - _SEGGER_RTT.aDown[n].RdOff) + +/********************************************************************* +* +* RTT "Terminal" API functions +* +********************************************************************** +*/ +int SEGGER_RTT_SetTerminal (char TerminalId); +int SEGGER_RTT_TerminalOut (char TerminalId, const char* s); + +/********************************************************************* +* +* RTT printf functions (require SEGGER_RTT_printf.c) +* +********************************************************************** +*/ +int SEGGER_RTT_printf(unsigned BufferIndex, const char * sFormat, ...); +#ifdef __cplusplus + } +#endif + +/********************************************************************* +* +* Defines +* +********************************************************************** +*/ + +// +// Operating modes. Define behavior if buffer is full (not enough space for entire message) +// +#define SEGGER_RTT_MODE_NO_BLOCK_SKIP (0U) // Skip. Do not block, output nothing. (Default) +#define SEGGER_RTT_MODE_NO_BLOCK_TRIM (1U) // Trim: Do not block, output as much as fits. +#define SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL (2U) // Block: Wait until there is space in the buffer. +#define SEGGER_RTT_MODE_MASK (3U) + +// +// Control sequences, based on ANSI. +// Can be used to control color, and clear the screen +// +#define RTT_CTRL_RESET "" // Reset to default colors +#define RTT_CTRL_CLEAR "" // Clear screen, reposition cursor to top left + +#define RTT_CTRL_TEXT_BLACK "" +#define RTT_CTRL_TEXT_RED "" +#define RTT_CTRL_TEXT_GREEN "" +#define RTT_CTRL_TEXT_YELLOW "" +#define RTT_CTRL_TEXT_BLUE "" +#define RTT_CTRL_TEXT_MAGENTA "" +#define RTT_CTRL_TEXT_CYAN "" +#define RTT_CTRL_TEXT_WHITE "" + +#define RTT_CTRL_TEXT_BRIGHT_BLACK "" +#define RTT_CTRL_TEXT_BRIGHT_RED "" +#define RTT_CTRL_TEXT_BRIGHT_GREEN "" +#define RTT_CTRL_TEXT_BRIGHT_YELLOW "" +#define RTT_CTRL_TEXT_BRIGHT_BLUE "" +#define RTT_CTRL_TEXT_BRIGHT_MAGENTA "" +#define RTT_CTRL_TEXT_BRIGHT_CYAN "" +#define RTT_CTRL_TEXT_BRIGHT_WHITE "" + +#define RTT_CTRL_BG_BLACK "" +#define RTT_CTRL_BG_RED "" +#define RTT_CTRL_BG_GREEN "" +#define RTT_CTRL_BG_YELLOW "" +#define RTT_CTRL_BG_BLUE "" +#define RTT_CTRL_BG_MAGENTA "" +#define RTT_CTRL_BG_CYAN "" +#define RTT_CTRL_BG_WHITE "" + +#define RTT_CTRL_BG_BRIGHT_BLACK "" +#define RTT_CTRL_BG_BRIGHT_RED "" +#define RTT_CTRL_BG_BRIGHT_GREEN "" +#define RTT_CTRL_BG_BRIGHT_YELLOW "" +#define RTT_CTRL_BG_BRIGHT_BLUE "" +#define RTT_CTRL_BG_BRIGHT_MAGENTA "" +#define RTT_CTRL_BG_BRIGHT_CYAN "" +#define RTT_CTRL_BG_BRIGHT_WHITE "" + + +#endif + +/*************************** End of file ****************************/ diff --git a/examples/device/nrf52840/src/segger_rtt/SEGGER_RTT_Conf.h b/examples/device/nrf52840/src/segger_rtt/SEGGER_RTT_Conf.h new file mode 100644 index 000000000..aef3b4053 --- /dev/null +++ b/examples/device/nrf52840/src/segger_rtt/SEGGER_RTT_Conf.h @@ -0,0 +1,242 @@ +/********************************************************************* +* SEGGER MICROCONTROLLER GmbH & Co. KG * +* Solutions for real time microcontroller applications * +********************************************************************** +* * +* (c) 2014 - 2016 SEGGER Microcontroller GmbH & Co. KG * +* * +* www.segger.com Support: support@segger.com * +* * +********************************************************************** +* * +* SEGGER RTT * Real Time Transfer for embedded targets * +* * +********************************************************************** +* * +* All rights reserved. * +* * +* * This software may in its unmodified form be freely redistributed * +* in source form. * +* * The source code may be modified, provided the source code * +* retains the above copyright notice, this list of conditions and * +* the following disclaimer. * +* * Modified versions of this software in source or linkable form * +* may not be distributed without prior consent of SEGGER. * +* * This software may only be used for communication with SEGGER * +* J-Link debug probes. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * +* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * +* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * +* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * +* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * +* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * +* DAMAGE. * +* * +********************************************************************** +* * +* RTT version: 5.12e * +* * +********************************************************************** +---------------------------------------------------------------------- +File : SEGGER_RTT_Conf.h +Purpose : Implementation of SEGGER real-time transfer (RTT) which + allows real-time communication on targets which support + debugger memory accesses while the CPU is running. +---------------------------END-OF-HEADER------------------------------ +*/ + +#ifndef SEGGER_RTT_CONF_H +#define SEGGER_RTT_CONF_H + +#ifdef __ICCARM__ + #include +#endif + +/********************************************************************* +* +* Defines, configurable +* +********************************************************************** +*/ + +#define SEGGER_RTT_MAX_NUM_UP_BUFFERS (2) // Max. number of up-buffers (T->H) available on this target (Default: 2) +#define SEGGER_RTT_MAX_NUM_DOWN_BUFFERS (2) // Max. number of down-buffers (H->T) available on this target (Default: 2) + +#define BUFFER_SIZE_UP (1024) // Size of the buffer for terminal output of target, up to host (Default: 1k) +#define BUFFER_SIZE_DOWN (16) // Size of the buffer for terminal input to target from host (Usually keyboard input) (Default: 16) + +#define SEGGER_RTT_PRINTF_BUFFER_SIZE (64u) // Size of buffer for RTT printf to bulk-send chars via RTT (Default: 64) + +#define SEGGER_RTT_MODE_DEFAULT SEGGER_RTT_MODE_NO_BLOCK_SKIP // Mode for pre-initialized terminal channel (buffer 0) + +// +// Target is not allowed to perform other RTT operations while string still has not been stored completely. +// Otherwise we would probably end up with a mixed string in the buffer. +// If using RTT from within interrupts, multiple tasks or multi processors, define the SEGGER_RTT_LOCK() and SEGGER_RTT_UNLOCK() function here. +// +// SEGGER_RTT_MAX_INTERRUPT_PRIORITY can be used in the sample lock routines on Cortex-M3/4. +// Make sure to mask all interrupts which can send RTT data, i.e. generate SystemView events, or cause task switches. +// When high-priority interrupts must not be masked while sending RTT data, SEGGER_RTT_MAX_INTERRUPT_PRIORITY needs to be adjusted accordingly. +// (Higher priority = lower priority number) +// Default value for embOS: 128u +// Default configuration in FreeRTOS: configMAX_SYSCALL_INTERRUPT_PRIORITY: ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) ) +// In case of doubt mask all interrupts: 0u +// + +#define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20) // Interrupt priority to lock on SEGGER_RTT_LOCK on Cortex-M3/4 (Default: 0x20) + +/********************************************************************* +* +* RTT lock configuration for SEGGER Embedded Studio, +* Rowley CrossStudio and GCC +*/ +#if (defined __SES_ARM) || (defined __CROSSWORKS_ARM) || (defined __GNUC__) + #ifdef __ARM_ARCH_6M__ + #define SEGGER_RTT_LOCK() { \ + unsigned int LockState; \ + __asm volatile ("mrs %0, primask \n\t" \ + "mov r1, $1 \n\t" \ + "msr primask, r1 \n\t" \ + : "=r" (LockState) \ + : \ + : "r1" \ + ); + + #define SEGGER_RTT_UNLOCK() __asm volatile ("msr primask, %0 \n\t" \ + : \ + : "r" (LockState) \ + : \ + ); \ + } + + #elif (defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)) + #ifndef SEGGER_RTT_MAX_INTERRUPT_PRIORITY + #define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20) + #endif + #define SEGGER_RTT_LOCK() { \ + unsigned int LockState; \ + __asm volatile ("mrs %0, basepri \n\t" \ + "mov r1, %1 \n\t" \ + "msr basepri, r1 \n\t" \ + : "=r" (LockState) \ + : "i"(SEGGER_RTT_MAX_INTERRUPT_PRIORITY) \ + : "r1" \ + ); + + #define SEGGER_RTT_UNLOCK() __asm volatile ("msr basepri, %0 \n\t" \ + : \ + : "r" (LockState) \ + : \ + ); \ + } + + #elif defined(__ARM_ARCH_7A__) + #define SEGGER_RTT_LOCK() { \ + unsigned int LockState; \ + __asm volatile ("mrs r1, CPSR \n\t" \ + "mov %0, r1 \n\t" \ + "orr r1, r1, #0xC0 \n\t" \ + "msr CPSR_c, r1 \n\t" \ + : "=r" (LockState) \ + : \ + : "r1" \ + ); + + #define SEGGER_RTT_UNLOCK() __asm volatile ("mov r0, %0 \n\t" \ + "mrs r1, CPSR \n\t" \ + "bic r1, r1, #0xC0 \n\t" \ + "and r0, r0, #0xC0 \n\t" \ + "orr r1, r1, r0 \n\t" \ + "msr CPSR_c, r1 \n\t" \ + : \ + : "r" (LockState) \ + : "r0", "r1" \ + ); \ + } +#else + #define SEGGER_RTT_LOCK() + #define SEGGER_RTT_UNLOCK() + #endif +#endif + +/********************************************************************* +* +* RTT lock configuration for IAR EWARM +*/ +#ifdef __ICCARM__ + #if (defined (__ARM6M__) && (__CORE__ == __ARM6M__)) + #define SEGGER_RTT_LOCK() { \ + unsigned int LockState; \ + LockState = __get_PRIMASK(); \ + __set_PRIMASK(1); + + #define SEGGER_RTT_UNLOCK() __set_PRIMASK(LockState); \ + } + #elif ((defined (__ARM7EM__) && (__CORE__ == __ARM7EM__)) || (defined (__ARM7M__) && (__CORE__ == __ARM7M__))) + #ifndef SEGGER_RTT_MAX_INTERRUPT_PRIORITY + #define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20) + #endif + #define SEGGER_RTT_LOCK() { \ + unsigned int LockState; \ + LockState = __get_BASEPRI(); \ + __set_BASEPRI(SEGGER_RTT_MAX_INTERRUPT_PRIORITY); + + #define SEGGER_RTT_UNLOCK() __set_BASEPRI(LockState); \ + } + #endif +#endif + +/********************************************************************* +* +* RTT lock configuration for KEIL ARM +*/ +#ifdef __CC_ARM + #if (defined __TARGET_ARCH_6S_M) + #define SEGGER_RTT_LOCK() { \ + unsigned int LockState; \ + register unsigned char PRIMASK __asm( "primask"); \ + LockState = PRIMASK; \ + PRIMASK = 1u; \ + __schedule_barrier(); + + #define SEGGER_RTT_UNLOCK() PRIMASK = LockState; \ + __schedule_barrier(); \ + } + #elif (defined(__TARGET_ARCH_7_M) || defined(__TARGET_ARCH_7E_M)) + #ifndef SEGGER_RTT_MAX_INTERRUPT_PRIORITY + #define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20) + #endif + #define SEGGER_RTT_LOCK() { \ + unsigned int LockState; \ + register unsigned char BASEPRI __asm( "basepri"); \ + LockState = BASEPRI; \ + BASEPRI = SEGGER_RTT_MAX_INTERRUPT_PRIORITY; \ + __schedule_barrier(); + + #define SEGGER_RTT_UNLOCK() BASEPRI = LockState; \ + __schedule_barrier(); \ + } + #endif +#endif + +/********************************************************************* +* +* RTT lock configuration fallback +*/ +#ifndef SEGGER_RTT_LOCK + #define SEGGER_RTT_LOCK() // Lock RTT (nestable) (i.e. disable interrupts) +#endif + +#ifndef SEGGER_RTT_UNLOCK + #define SEGGER_RTT_UNLOCK() // Unlock RTT (nestable) (i.e. enable previous interrupt lock state) +#endif + +#endif +/*************************** End of file ****************************/ diff --git a/examples/device/nrf52840/src/segger_rtt/SEGGER_RTT_SES.c b/examples/device/nrf52840/src/segger_rtt/SEGGER_RTT_SES.c new file mode 100644 index 000000000..e6634147c --- /dev/null +++ b/examples/device/nrf52840/src/segger_rtt/SEGGER_RTT_SES.c @@ -0,0 +1,76 @@ +/********************************************************************* +* SEGGER MICROCONTROLLER GmbH & Co. KG * +* Solutions for real time microcontroller applications * +********************************************************************** +* * +* (c) 2014 - 2015 SEGGER Microcontroller GmbH & Co. KG * +* * +* www.segger.com Support: support@segger.com * +* * +********************************************************************** +* * +* All rights reserved. * +* * +* * This software may in its unmodified form be freely redistributed * +* in source form. * +* * The source code may be modified, provided the source code * +* retains the above copyright notice, this list of conditions and * +* the following disclaimer. * +* * Modified versions of this software in source or linkable form * +* may not be distributed without prior consent of SEGGER. * +* * This software may only be used for communication with SEGGER * +* J-Link debug probes. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * +* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * +* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * +* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * +* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * +* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * +* DAMAGE. * +* * +********************************************************************** +-------- END-OF-HEADER --------------------------------------------- +File : SEGGER_RTT_Syscalls_SES.c +Purpose : Reimplementation of printf, puts and + implementation of __putchar and __getchar using RTT in SES. + To use RTT for printf output, include this file in your + application. +---------------------------------------------------------------------- +*/ +#include "SEGGER_RTT.h" +#include "__libc.h" +#include +#include + +int printf(const char *fmt,...) { + char buffer[128]; + va_list args; + va_start (args, fmt); + int n = vsnprintf(buffer, sizeof(buffer), fmt, args); + SEGGER_RTT_Write(0, buffer, n); + va_end(args); + return n; +} + +int puts(const char *s) { + return SEGGER_RTT_WriteString(0, s); +} + +int __putchar(int x, __printf_tag_ptr ctx) { + (void)ctx; + SEGGER_RTT_Write(0, (char *)&x, 1); + return x; +} + +int __getchar() { + return SEGGER_RTT_WaitKey(); +} + +/****** End Of File *************************************************/ diff --git a/examples/device/nrf52840_freertos/segger/SEGGER_RTT.c b/examples/device/nrf52840_freertos/segger/SEGGER_RTT.c deleted file mode 100644 index aee5bd21e..000000000 --- a/examples/device/nrf52840_freertos/segger/SEGGER_RTT.c +++ /dev/null @@ -1,1329 +0,0 @@ -/********************************************************************* -* SEGGER MICROCONTROLLER GmbH & Co. KG * -* Solutions for real time microcontroller applications * -********************************************************************** -* * -* (c) 2014 - 2016 SEGGER Microcontroller GmbH & Co. KG * -* * -* www.segger.com Support: support@segger.com * -* * -********************************************************************** -* * -* SEGGER RTT * Real Time Transfer for embedded targets * -* * -********************************************************************** -* * -* All rights reserved. * -* * -* * This software may in its unmodified form be freely redistributed * -* in source form. * -* * The source code may be modified, provided the source code * -* retains the above copyright notice, this list of conditions and * -* the following disclaimer. * -* * Modified versions of this software in source or linkable form * -* may not be distributed without prior consent of SEGGER. * -* * This software may only be used for communication with SEGGER * -* J-Link debug probes. * -* * -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * -* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * -* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * -* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * -* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR * -* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * -* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * -* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * -* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * -* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * -* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * -* DAMAGE. * -* * -********************************************************************** -* * -* RTT version: 5.12e * -* * -********************************************************************** ----------------------------END-OF-HEADER------------------------------ -File : SEGGER_RTT.c -Purpose : Implementation of SEGGER real-time transfer (RTT) which - allows real-time communication on targets which support - debugger memory accesses while the CPU is running. - -Additional information: - Type "int" is assumed to be 32-bits in size - H->T Host to target communication - T->H Target to host communication - - RTT channel 0 is always present and reserved for Terminal usage. - Name is fixed to "Terminal" - - Effective buffer size: SizeOfBuffer - 1 - - WrOff == RdOff: Buffer is empty - WrOff == (RdOff - 1): Buffer is full - WrOff > RdOff: Free space includes wrap-around - WrOff < RdOff: Used space includes wrap-around - (WrOff == (SizeOfBuffer - 1)) && (RdOff == 0): - Buffer full and wrap-around after next byte - - ----------------------------------------------------------------------- -*/ - -#include "SEGGER_RTT.h" - -#include // for memcpy - -/********************************************************************* -* -* Configuration, default values -* -********************************************************************** -*/ - -#ifndef BUFFER_SIZE_UP - #define BUFFER_SIZE_UP 1024 // Size of the buffer for terminal output of target, up to host -#endif - -#ifndef BUFFER_SIZE_DOWN - #define BUFFER_SIZE_DOWN 16 // Size of the buffer for terminal input to target from host (Usually keyboard input) -#endif - -#ifndef SEGGER_RTT_MAX_NUM_UP_BUFFERS - #define SEGGER_RTT_MAX_NUM_UP_BUFFERS 2 // Number of up-buffers (T->H) available on this target -#endif - -#ifndef SEGGER_RTT_MAX_NUM_DOWN_BUFFERS - #define SEGGER_RTT_MAX_NUM_DOWN_BUFFERS 2 // Number of down-buffers (H->T) available on this target -#endif - -#ifndef SEGGER_RTT_BUFFER_SECTION - #if defined SEGGER_RTT_SECTION - #define SEGGER_RTT_BUFFER_SECTION SEGGER_RTT_SECTION - #endif -#endif - -#ifndef SEGGER_RTT_MODE_DEFAULT - #define SEGGER_RTT_MODE_DEFAULT SEGGER_RTT_MODE_NO_BLOCK_SKIP -#endif - -#ifndef SEGGER_RTT_LOCK - #define SEGGER_RTT_LOCK() -#endif - -#ifndef SEGGER_RTT_UNLOCK - #define SEGGER_RTT_UNLOCK() -#endif - -#ifndef STRLEN - #define STRLEN(a) strlen((a)) -#endif - -#ifndef MEMCPY - #define MEMCPY(pDest, pSrc, NumBytes) memcpy((pDest), (pSrc), (NumBytes)) -#endif - -#ifndef MIN - #define MIN(a, b) (((a) < (b)) ? (a) : (b)) -#endif - -#ifndef MAX - #define MAX(a, b) (((a) > (b)) ? (a) : (b)) -#endif -// -// For some environments, NULL may not be defined until certain headers are included -// -#ifndef NULL - #define NULL 0 -#endif - -/********************************************************************* -* -* Static const data -* -********************************************************************** -*/ - -static unsigned char _aTerminalId[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; - -/********************************************************************* -* -* Static data -* -********************************************************************** -*/ -// -// RTT Control Block and allocate buffers for channel 0 -// -#ifdef SEGGER_RTT_SECTION - #if (defined __GNUC__) - __attribute__ ((section (SEGGER_RTT_SECTION))) SEGGER_RTT_CB _SEGGER_RTT; - #elif (defined __ICCARM__) || (defined __ICCRX__) - #pragma location=SEGGER_RTT_SECTION - SEGGER_RTT_CB _SEGGER_RTT; - #elif (defined __CC_ARM__) - __attribute__ ((section (SEGGER_RTT_SECTION), zero_init)) SEGGER_RTT_CB _SEGGER_RTT; - #else - SEGGER_RTT_CB _SEGGER_RTT; - #endif -#else - SEGGER_RTT_CB _SEGGER_RTT; -#endif - -#ifdef SEGGER_RTT_BUFFER_SECTION - #if (defined __GNUC__) - __attribute__ ((section (SEGGER_RTT_BUFFER_SECTION))) static char _acUpBuffer [BUFFER_SIZE_UP]; - __attribute__ ((section (SEGGER_RTT_BUFFER_SECTION))) static char _acDownBuffer[BUFFER_SIZE_DOWN]; - #elif (defined __ICCARM__) || (defined __ICCRX__) - #pragma location=SEGGER_RTT_BUFFER_SECTION - static char _acUpBuffer [BUFFER_SIZE_UP]; - #pragma location=SEGGER_RTT_BUFFER_SECTION - static char _acDownBuffer[BUFFER_SIZE_DOWN]; - #elif (defined __CC_ARM__) - __attribute__ ((section (SEGGER_RTT_BUFFER_SECTION), zero_init)) static char _acUpBuffer [BUFFER_SIZE_UP]; - __attribute__ ((section (SEGGER_RTT_BUFFER_SECTION), zero_init)) static char _acDownBuffer[BUFFER_SIZE_DOWN]; - #else - static char _acUpBuffer [BUFFER_SIZE_UP]; - static char _acDownBuffer[BUFFER_SIZE_DOWN]; - #endif -#else - static char _acUpBuffer [BUFFER_SIZE_UP]; - static char _acDownBuffer[BUFFER_SIZE_DOWN]; -#endif - -static char _ActiveTerminal; - -/********************************************************************* -* -* Static functions -* -********************************************************************** -*/ - -/********************************************************************* -* -* _DoInit() -* -* Function description -* Initializes the control block an buffers. -* May only be called via INIT() to avoid overriding settings. -* -*/ -#define INIT() do { \ - if (_SEGGER_RTT.acID[0] == '\0') { _DoInit(); } \ - } while (0) -static void _DoInit(void) { - SEGGER_RTT_CB* p; - // - // Initialize control block - // - p = &_SEGGER_RTT; - p->MaxNumUpBuffers = SEGGER_RTT_MAX_NUM_UP_BUFFERS; - p->MaxNumDownBuffers = SEGGER_RTT_MAX_NUM_DOWN_BUFFERS; - // - // Initialize up buffer 0 - // - p->aUp[0].sName = "Terminal"; - p->aUp[0].pBuffer = _acUpBuffer; - p->aUp[0].SizeOfBuffer = sizeof(_acUpBuffer); - p->aUp[0].RdOff = 0u; - p->aUp[0].WrOff = 0u; - p->aUp[0].Flags = SEGGER_RTT_MODE_DEFAULT; - // - // Initialize down buffer 0 - // - p->aDown[0].sName = "Terminal"; - p->aDown[0].pBuffer = _acDownBuffer; - p->aDown[0].SizeOfBuffer = sizeof(_acDownBuffer); - p->aDown[0].RdOff = 0u; - p->aDown[0].WrOff = 0u; - p->aDown[0].Flags = SEGGER_RTT_MODE_DEFAULT; - // - // Finish initialization of the control block. - // Copy Id string in three steps to make sure "SEGGER RTT" is not found - // in initializer memory (usually flash) by J-Link - // - strcpy(&p->acID[7], "RTT"); - strcpy(&p->acID[0], "SEGGER"); - p->acID[6] = ' '; -} - -/********************************************************************* -* -* _WriteBlocking() -* -* Function description -* Stores a specified number of characters in SEGGER RTT ring buffer -* and updates the associated write pointer which is periodically -* read by the host. -* The caller is responsible for managing the write chunk sizes as -* _WriteBlocking() will block until all data has been posted successfully. -* -* Parameters -* pRing Ring buffer to post to. -* pBuffer Pointer to character array. Does not need to point to a \0 terminated string. -* NumBytes Number of bytes to be stored in the SEGGER RTT control block. -* -* Return value -* >= 0 - Number of bytes written into buffer. -*/ -static unsigned _WriteBlocking(SEGGER_RTT_BUFFER_UP* pRing, const char* pBuffer, unsigned NumBytes) { - unsigned NumBytesToWrite; - unsigned NumBytesWritten; - unsigned RdOff; - unsigned WrOff; - // - // Write data to buffer and handle wrap-around if necessary - // - NumBytesWritten = 0u; - WrOff = pRing->WrOff; - do { - RdOff = pRing->RdOff; // May be changed by host (debug probe) in the meantime - if (RdOff > WrOff) { - NumBytesToWrite = RdOff - WrOff - 1u; - } else { - NumBytesToWrite = pRing->SizeOfBuffer - (WrOff - RdOff + 1u); - } - NumBytesToWrite = MIN(NumBytesToWrite, (pRing->SizeOfBuffer - WrOff)); // Number of bytes that can be written until buffer wrap-around - NumBytesToWrite = MIN(NumBytesToWrite, NumBytes); - memcpy(pRing->pBuffer + WrOff, pBuffer, NumBytesToWrite); - NumBytesWritten += NumBytesToWrite; - pBuffer += NumBytesToWrite; - NumBytes -= NumBytesToWrite; - WrOff += NumBytesToWrite; - if (WrOff == pRing->SizeOfBuffer) { - WrOff = 0u; - } - pRing->WrOff = WrOff; - } while (NumBytes); - // - return NumBytesWritten; -} - -/********************************************************************* -* -* _WriteNoCheck() -* -* Function description -* Stores a specified number of characters in SEGGER RTT ring buffer -* and updates the associated write pointer which is periodically -* read by the host. -* It is callers responsibility to make sure data actually fits in buffer. -* -* Parameters -* pRing Ring buffer to post to. -* pBuffer Pointer to character array. Does not need to point to a \0 terminated string. -* NumBytes Number of bytes to be stored in the SEGGER RTT control block. -* -* Notes -* (1) If there might not be enough space in the "Up"-buffer, call _WriteBlocking -*/ -static void _WriteNoCheck(SEGGER_RTT_BUFFER_UP* pRing, const char* pData, unsigned NumBytes) { - unsigned NumBytesAtOnce; - unsigned WrOff; - unsigned Rem; - - WrOff = pRing->WrOff; - Rem = pRing->SizeOfBuffer - WrOff; - if (Rem > NumBytes) { - // - // All data fits before wrap around - // - memcpy(pRing->pBuffer + WrOff, pData, NumBytes); - pRing->WrOff = WrOff + NumBytes; - } else { - // - // We reach the end of the buffer, so need to wrap around - // - NumBytesAtOnce = Rem; - memcpy(pRing->pBuffer + WrOff, pData, NumBytesAtOnce); - NumBytesAtOnce = NumBytes - Rem; - memcpy(pRing->pBuffer, pData + Rem, NumBytesAtOnce); - pRing->WrOff = NumBytesAtOnce; - } -} - -/********************************************************************* -* -* _PostTerminalSwitch() -* -* Function description -* Switch terminal to the given terminal ID. It is the caller's -* responsibility to ensure the terminal ID is correct and there is -* enough space in the buffer for this to complete successfully. -* -* Parameters -* pRing Ring buffer to post to. -* TerminalId Terminal ID to switch to. -*/ -static void _PostTerminalSwitch(SEGGER_RTT_BUFFER_UP* pRing, unsigned char TerminalId) { - char ac[2]; - - ac[0] = 0xFFu; - ac[1] = _aTerminalId[TerminalId]; // Caller made already sure that TerminalId does not exceed our terminal limit - _WriteBlocking(pRing, ac, 2u); -} - -/********************************************************************* -* -* _GetAvailWriteSpace() -* -* Function description -* Returns the number of bytes that can be written to the ring -* buffer without blocking. -* -* Parameters -* pRing Ring buffer to check. -* -* Return value -* Number of bytes that are free in the buffer. -*/ -static unsigned _GetAvailWriteSpace(SEGGER_RTT_BUFFER_UP* pRing) { - unsigned RdOff; - unsigned WrOff; - unsigned r; - // - // Avoid warnings regarding volatile access order. It's not a problem - // in this case, but dampen compiler enthusiasm. - // - RdOff = pRing->RdOff; - WrOff = pRing->WrOff; - if (RdOff <= WrOff) { - r = pRing->SizeOfBuffer - 1u - WrOff + RdOff; - } else { - r = RdOff - WrOff - 1u; - } - return r; -} - -/********************************************************************* -* -* Public code -* -********************************************************************** -*/ -/********************************************************************* -* -* SEGGER_RTT_ReadNoLock() -* -* Function description -* Reads characters from SEGGER real-time-terminal control block -* which have been previously stored by the host. -* Do not lock against interrupts and multiple access. -* -* Parameters -* BufferIndex Index of Down-buffer to be used (e.g. 0 for "Terminal"). -* pBuffer Pointer to buffer provided by target application, to copy characters from RTT-down-buffer to. -* BufferSize Size of the target application buffer. -* -* Return value -* Number of bytes that have been read. -*/ -unsigned SEGGER_RTT_ReadNoLock(unsigned BufferIndex, void* pData, unsigned BufferSize) { - unsigned NumBytesRem; - unsigned NumBytesRead; - unsigned RdOff; - unsigned WrOff; - unsigned char* pBuffer; - SEGGER_RTT_BUFFER_DOWN* pRing; - // - INIT(); - pRing = &_SEGGER_RTT.aDown[BufferIndex]; - pBuffer = (unsigned char*)pData; - RdOff = pRing->RdOff; - WrOff = pRing->WrOff; - NumBytesRead = 0u; - // - // Read from current read position to wrap-around of buffer, first - // - if (RdOff > WrOff) { - NumBytesRem = pRing->SizeOfBuffer - RdOff; - NumBytesRem = MIN(NumBytesRem, BufferSize); - memcpy(pBuffer, pRing->pBuffer + RdOff, NumBytesRem); - NumBytesRead += NumBytesRem; - pBuffer += NumBytesRem; - BufferSize -= NumBytesRem; - RdOff += NumBytesRem; - // - // Handle wrap-around of buffer - // - if (RdOff == pRing->SizeOfBuffer) { - RdOff = 0u; - } - } - // - // Read remaining items of buffer - // - NumBytesRem = WrOff - RdOff; - NumBytesRem = MIN(NumBytesRem, BufferSize); - if (NumBytesRem > 0u) { - memcpy(pBuffer, pRing->pBuffer + RdOff, NumBytesRem); - NumBytesRead += NumBytesRem; - pBuffer += NumBytesRem; - BufferSize -= NumBytesRem; - RdOff += NumBytesRem; - } - if (NumBytesRead) { - pRing->RdOff = RdOff; - } - // - return NumBytesRead; -} - -/********************************************************************* -* -* SEGGER_RTT_Read -* -* Function description -* Reads characters from SEGGER real-time-terminal control block -* which have been previously stored by the host. -* -* Parameters -* BufferIndex Index of Down-buffer to be used (e.g. 0 for "Terminal"). -* pBuffer Pointer to buffer provided by target application, to copy characters from RTT-down-buffer to. -* BufferSize Size of the target application buffer. -* -* Return value -* Number of bytes that have been read. -*/ -unsigned SEGGER_RTT_Read(unsigned BufferIndex, void* pBuffer, unsigned BufferSize) { - unsigned NumBytesRead; - // - SEGGER_RTT_LOCK(); - // - // Call the non-locking read function - // - NumBytesRead = SEGGER_RTT_ReadNoLock(BufferIndex, pBuffer, BufferSize); - // - // Finish up. - // - SEGGER_RTT_UNLOCK(); - // - return NumBytesRead; -} - -/********************************************************************* -* -* SEGGER_RTT_WriteWithOverwriteNoLock -* -* Function description -* Stores a specified number of characters in SEGGER RTT -* control block. -* SEGGER_RTT_WriteWithOverwriteNoLock does not lock the application -* and overwrites data if the data does not fit into the buffer. -* -* Parameters -* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). -* pBuffer Pointer to character array. Does not need to point to a \0 terminated string. -* NumBytes Number of bytes to be stored in the SEGGER RTT control block. -* -* Notes -* (1) If there is not enough space in the "Up"-buffer, data is overwritten. -* (2) For performance reasons this function does not call Init() -* and may only be called after RTT has been initialized. -* Either by calling SEGGER_RTT_Init() or calling another RTT API function first. -* (3) Do not use SEGGER_RTT_WriteWithOverwriteNoLock if a J-Link -* connection reads RTT data. -*/ -void SEGGER_RTT_WriteWithOverwriteNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) { - const char* pData; - SEGGER_RTT_BUFFER_UP* pRing; - unsigned Avail; - - pData = (const char *)pBuffer; - // - // Get "to-host" ring buffer and copy some elements into local variables. - // - pRing = &_SEGGER_RTT.aUp[BufferIndex]; - // - // Check if we will overwrite data and need to adjust the RdOff. - // - if (pRing->WrOff == pRing->RdOff) { - Avail = pRing->SizeOfBuffer - 1u; - } else if ( pRing->WrOff < pRing->RdOff) { - Avail = pRing->RdOff - pRing->WrOff - 1u; - } else { - Avail = pRing->RdOff - pRing->WrOff - 1u + pRing->SizeOfBuffer; - } - if (NumBytes > Avail) { - pRing->RdOff += (NumBytes - Avail); - while (pRing->RdOff >= pRing->SizeOfBuffer) { - pRing->RdOff -= pRing->SizeOfBuffer; - } - } - // - // Write all data, no need to check the RdOff, but possibly handle multiple wrap-arounds - // - Avail = pRing->SizeOfBuffer - pRing->WrOff; - do { - if (Avail > NumBytes) { - // - // Last round - // -#if 1 // memcpy() is good for large amounts of data, but the overhead is too big for small amounts. Use a simple byte loop instead. - char* pDst; - pDst = pRing->pBuffer + pRing->WrOff; - pRing->WrOff += NumBytes; - do { - *pDst++ = *pData++; - } while (--NumBytes); -#else - memcpy(pRing->pBuffer + WrOff, pData, NumBytes); - pRing->WrOff += NumBytes; -#endif - break; //Alternatively: NumBytes = 0; - } else { - // - // Wrap-around necessary, write until wrap-around and reset WrOff - // - memcpy(pRing->pBuffer + pRing->WrOff, pData, Avail); - pData += Avail; - pRing->WrOff = 0; - NumBytes -= Avail; - Avail = (pRing->SizeOfBuffer - 1); - } - } while (NumBytes); -} - -/********************************************************************* -* -* SEGGER_RTT_WriteSkipNoLock -* -* Function description -* Stores a specified number of characters in SEGGER RTT -* control block which is then read by the host. -* SEGGER_RTT_WriteSkipNoLock does not lock the application and -* skips all data, if the data does not fit into the buffer. -* -* Parameters -* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). -* pBuffer Pointer to character array. Does not need to point to a \0 terminated string. -* NumBytes Number of bytes to be stored in the SEGGER RTT control block. -* -* Return value -* Number of bytes which have been stored in the "Up"-buffer. -* -* Notes -* (1) If there is not enough space in the "Up"-buffer, all data is dropped. -* (2) For performance reasons this function does not call Init() -* and may only be called after RTT has been initialized. -* Either by calling SEGGER_RTT_Init() or calling another RTT API function first. -*/ -unsigned SEGGER_RTT_WriteSkipNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) { - const char* pData; - SEGGER_RTT_BUFFER_UP* pRing; - unsigned Avail; - unsigned RdOff; - unsigned WrOff; - unsigned Rem; - - pData = (const char *)pBuffer; - // - // Get "to-host" ring buffer and copy some elements into local variables. - // - pRing = &_SEGGER_RTT.aUp[BufferIndex]; - RdOff = pRing->RdOff; - WrOff = pRing->WrOff; - // - // Handle the most common cases fastest. - // Which is: - // RdOff <= WrOff -> Space until wrap around is free. - // AND - // WrOff + NumBytes < SizeOfBuffer -> No Wrap around necessary. - // - // OR - // - // RdOff > WrOff -> Space until RdOff - 1 is free. - // AND - // WrOff + NumBytes < RdOff -> Data fits into buffer - // - if (RdOff <= WrOff) { - // - // Get space until WrOff will be at wrap around. - // - Avail = pRing->SizeOfBuffer - 1u - WrOff ; - if (Avail >= NumBytes) { -#if 1 // memcpy() is good for large amounts of data, but the overhead is too big for small amounts. Use a simple byte loop instead. - char* pDst; - pDst = pRing->pBuffer + WrOff; - WrOff += NumBytes; - do { - *pDst++ = *pData++; - } while (--NumBytes); - pRing->WrOff = WrOff + NumBytes; -#else - memcpy(pRing->pBuffer + WrOff, pData, NumBytes); - pRing->WrOff = WrOff + NumBytes; -#endif - return 1; - } - // - // If data did not fit into space until wrap around calculate complete space in buffer. - // - Avail += RdOff; - // - // If there is still no space for the whole of this output, don't bother. - // - if (Avail >= NumBytes) { - // - // OK, we have enough space in buffer. Copy in one or 2 chunks - // - Rem = pRing->SizeOfBuffer - WrOff; // Space until end of buffer - if (Rem > NumBytes) { - memcpy(pRing->pBuffer + WrOff, pData, NumBytes); - pRing->WrOff = WrOff + NumBytes; - } else { - // - // We reach the end of the buffer, so need to wrap around - // - memcpy(pRing->pBuffer + WrOff, pData, Rem); - memcpy(pRing->pBuffer, pData + Rem, NumBytes - Rem); - pRing->WrOff = NumBytes - Rem; - } - return 1; - } - } else { - Avail = RdOff - WrOff - 1u; - if (Avail >= NumBytes) { - memcpy(pRing->pBuffer + WrOff, pData, NumBytes); - pRing->WrOff = WrOff + NumBytes; - return 1; - } - } - // - // If we reach this point no data has been written - // - return 0; -} - -/********************************************************************* -* -* SEGGER_RTT_WriteNoLock -* -* Function description -* Stores a specified number of characters in SEGGER RTT -* control block which is then read by the host. -* SEGGER_RTT_WriteNoLock does not lock the application. -* -* Parameters -* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). -* pBuffer Pointer to character array. Does not need to point to a \0 terminated string. -* NumBytes Number of bytes to be stored in the SEGGER RTT control block. -* -* Return value -* Number of bytes which have been stored in the "Up"-buffer. -* -* Notes -* (1) If there is not enough space in the "Up"-buffer, remaining characters of pBuffer are dropped. -* (2) For performance reasons this function does not call Init() -* and may only be called after RTT has been initialized. -* Either by calling SEGGER_RTT_Init() or calling another RTT API function first. -*/ -unsigned SEGGER_RTT_WriteNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) { - unsigned Status; - unsigned Avail; - const char* pData; - SEGGER_RTT_BUFFER_UP* pRing; - - pData = (const char *)pBuffer; - // - // Get "to-host" ring buffer. - // - pRing = &_SEGGER_RTT.aUp[BufferIndex]; - // - // How we output depends upon the mode... - // - switch (pRing->Flags) { - case SEGGER_RTT_MODE_NO_BLOCK_SKIP: - // - // If we are in skip mode and there is no space for the whole - // of this output, don't bother. - // - Avail = _GetAvailWriteSpace(pRing); - if (Avail < NumBytes) { - Status = 0u; - } else { - Status = NumBytes; - _WriteNoCheck(pRing, pData, NumBytes); - } - break; - case SEGGER_RTT_MODE_NO_BLOCK_TRIM: - // - // If we are in trim mode, trim to what we can output without blocking. - // - Avail = _GetAvailWriteSpace(pRing); - Status = Avail < NumBytes ? Avail : NumBytes; - _WriteNoCheck(pRing, pData, Status); - break; - case SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL: - // - // If we are in blocking mode, output everything. - // - Status = _WriteBlocking(pRing, pData, NumBytes); - break; - default: - Status = 0u; - break; - } - // - // Finish up. - // - return Status; -} - -/********************************************************************* -* -* SEGGER_RTT_Write -* -* Function description -* Stores a specified number of characters in SEGGER RTT -* control block which is then read by the host. -* -* Parameters -* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). -* pBuffer Pointer to character array. Does not need to point to a \0 terminated string. -* NumBytes Number of bytes to be stored in the SEGGER RTT control block. -* -* Return value -* Number of bytes which have been stored in the "Up"-buffer. -* -* Notes -* (1) If there is not enough space in the "Up"-buffer, remaining characters of pBuffer are dropped. -*/ -unsigned SEGGER_RTT_Write(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) { - unsigned Status; - // - INIT(); - SEGGER_RTT_LOCK(); - // - // Call the non-locking write function - // - Status = SEGGER_RTT_WriteNoLock(BufferIndex, pBuffer, NumBytes); - // - // Finish up. - // - SEGGER_RTT_UNLOCK(); - // - return Status; -} - -/********************************************************************* -* -* SEGGER_RTT_WriteString -* -* Function description -* Stores string in SEGGER RTT control block. -* This data is read by the host. -* -* Parameters -* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). -* s Pointer to string. -* -* Return value -* Number of bytes which have been stored in the "Up"-buffer. -* -* Notes -* (1) If there is not enough space in the "Up"-buffer, depending on configuration, -* remaining characters may be dropped or RTT module waits until there is more space in the buffer. -* (2) String passed to this function has to be \0 terminated -* (3) \0 termination character is *not* stored in RTT buffer -*/ -unsigned SEGGER_RTT_WriteString(unsigned BufferIndex, const char* s) { - unsigned Len; - - Len = STRLEN(s); - return SEGGER_RTT_Write(BufferIndex, s, Len); -} - -/********************************************************************* -* -* SEGGER_RTT_GetKey -* -* Function description -* Reads one character from the SEGGER RTT buffer. -* Host has previously stored data there. -* -* Return value -* < 0 - No character available (buffer empty). -* >= 0 - Character which has been read. (Possible values: 0 - 255) -* -* Notes -* (1) This function is only specified for accesses to RTT buffer 0. -*/ -int SEGGER_RTT_GetKey(void) { - char c; - int r; - - r = (int)SEGGER_RTT_Read(0u, &c, 1u); - if (r == 1) { - r = (int)(unsigned char)c; - } else { - r = -1; - } - return r; -} - -/********************************************************************* -* -* SEGGER_RTT_WaitKey -* -* Function description -* Waits until at least one character is avaible in the SEGGER RTT buffer. -* Once a character is available, it is read and this function returns. -* -* Return value -* >=0 - Character which has been read. -* -* Notes -* (1) This function is only specified for accesses to RTT buffer 0 -* (2) This function is blocking if no character is present in RTT buffer -*/ -int SEGGER_RTT_WaitKey(void) { - int r; - - do { - r = SEGGER_RTT_GetKey(); - } while (r < 0); - return r; -} - -/********************************************************************* -* -* SEGGER_RTT_HasKey -* -* Function description -* Checks if at least one character for reading is available in the SEGGER RTT buffer. -* -* Return value -* == 0 - No characters are available to read. -* == 1 - At least one character is available. -* -* Notes -* (1) This function is only specified for accesses to RTT buffer 0 -*/ -int SEGGER_RTT_HasKey(void) { - unsigned RdOff; - int r; - - INIT(); - RdOff = _SEGGER_RTT.aDown[0].RdOff; - if (RdOff != _SEGGER_RTT.aDown[0].WrOff) { - r = 1; - } else { - r = 0; - } - return r; -} - -/********************************************************************* -* -* SEGGER_RTT_HasData -* -* Function description -* Check if there is data from the host in the given buffer. -* -* Return value: -* ==0: No data -* !=0: Data in buffer -* -*/ -unsigned SEGGER_RTT_HasData(unsigned BufferIndex) { - SEGGER_RTT_BUFFER_DOWN* pRing; - unsigned v; - - pRing = &_SEGGER_RTT.aDown[BufferIndex]; - v = pRing->WrOff; - return v - pRing->RdOff; -} - -/********************************************************************* -* -* SEGGER_RTT_AllocDownBuffer -* -* Function description -* Run-time configuration of the next down-buffer (H->T). -* The next buffer, which is not used yet is configured. -* This includes: Buffer address, size, name, flags, ... -* -* Parameters -* sName Pointer to a constant name string. -* pBuffer Pointer to a buffer to be used. -* BufferSize Size of the buffer. -* Flags Operating modes. Define behavior if buffer is full (not enough space for entire message). -* -* Return value -* >= 0 - O.K. Buffer Index -* < 0 - Error -*/ -int SEGGER_RTT_AllocDownBuffer(const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) { - int BufferIndex; - - INIT(); - SEGGER_RTT_LOCK(); - BufferIndex = 0; - do { - if (_SEGGER_RTT.aDown[BufferIndex].pBuffer == NULL) { - break; - } - BufferIndex++; - } while (BufferIndex < _SEGGER_RTT.MaxNumDownBuffers); - if (BufferIndex < _SEGGER_RTT.MaxNumDownBuffers) { - _SEGGER_RTT.aDown[BufferIndex].sName = sName; - _SEGGER_RTT.aDown[BufferIndex].pBuffer = pBuffer; - _SEGGER_RTT.aDown[BufferIndex].SizeOfBuffer = BufferSize; - _SEGGER_RTT.aDown[BufferIndex].RdOff = 0u; - _SEGGER_RTT.aDown[BufferIndex].WrOff = 0u; - _SEGGER_RTT.aDown[BufferIndex].Flags = Flags; - } else { - BufferIndex = -1; - } - SEGGER_RTT_UNLOCK(); - return BufferIndex; -} - -/********************************************************************* -* -* SEGGER_RTT_AllocUpBuffer -* -* Function description -* Run-time configuration of the next up-buffer (T->H). -* The next buffer, which is not used yet is configured. -* This includes: Buffer address, size, name, flags, ... -* -* Parameters -* sName Pointer to a constant name string. -* pBuffer Pointer to a buffer to be used. -* BufferSize Size of the buffer. -* Flags Operating modes. Define behavior if buffer is full (not enough space for entire message). -* -* Return value -* >= 0 - O.K. Buffer Index -* < 0 - Error -*/ -int SEGGER_RTT_AllocUpBuffer(const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) { - int BufferIndex; - - INIT(); - SEGGER_RTT_LOCK(); - BufferIndex = 0; - do { - if (_SEGGER_RTT.aUp[BufferIndex].pBuffer == NULL) { - break; - } - BufferIndex++; - } while (BufferIndex < _SEGGER_RTT.MaxNumUpBuffers); - if (BufferIndex < _SEGGER_RTT.MaxNumUpBuffers) { - _SEGGER_RTT.aUp[BufferIndex].sName = sName; - _SEGGER_RTT.aUp[BufferIndex].pBuffer = pBuffer; - _SEGGER_RTT.aUp[BufferIndex].SizeOfBuffer = BufferSize; - _SEGGER_RTT.aUp[BufferIndex].RdOff = 0u; - _SEGGER_RTT.aUp[BufferIndex].WrOff = 0u; - _SEGGER_RTT.aUp[BufferIndex].Flags = Flags; - } else { - BufferIndex = -1; - } - SEGGER_RTT_UNLOCK(); - return BufferIndex; -} - -/********************************************************************* -* -* SEGGER_RTT_ConfigUpBuffer -* -* Function description -* Run-time configuration of a specific up-buffer (T->H). -* Buffer to be configured is specified by index. -* This includes: Buffer address, size, name, flags, ... -* -* Parameters -* BufferIndex Index of the buffer to configure. -* sName Pointer to a constant name string. -* pBuffer Pointer to a buffer to be used. -* BufferSize Size of the buffer. -* Flags Operating modes. Define behavior if buffer is full (not enough space for entire message). -* -* Return value -* >= 0 - O.K. -* < 0 - Error -*/ -int SEGGER_RTT_ConfigUpBuffer(unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) { - int r; - - INIT(); - if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumUpBuffers) { - SEGGER_RTT_LOCK(); - if (BufferIndex > 0u) { - _SEGGER_RTT.aUp[BufferIndex].sName = sName; - _SEGGER_RTT.aUp[BufferIndex].pBuffer = pBuffer; - _SEGGER_RTT.aUp[BufferIndex].SizeOfBuffer = BufferSize; - _SEGGER_RTT.aUp[BufferIndex].RdOff = 0u; - _SEGGER_RTT.aUp[BufferIndex].WrOff = 0u; - } - _SEGGER_RTT.aUp[BufferIndex].Flags = Flags; - SEGGER_RTT_UNLOCK(); - r = 0; - } else { - r = -1; - } - return r; -} - -/********************************************************************* -* -* SEGGER_RTT_ConfigDownBuffer -* -* Function description -* Run-time configuration of a specific down-buffer (H->T). -* Buffer to be configured is specified by index. -* This includes: Buffer address, size, name, flags, ... -* -* Parameters -* BufferIndex Index of the buffer to configure. -* sName Pointer to a constant name string. -* pBuffer Pointer to a buffer to be used. -* BufferSize Size of the buffer. -* Flags Operating modes. Define behavior if buffer is full (not enough space for entire message). -* -* Return value -* >= 0 O.K. -* < 0 Error -*/ -int SEGGER_RTT_ConfigDownBuffer(unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) { - int r; - - INIT(); - if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumDownBuffers) { - SEGGER_RTT_LOCK(); - if (BufferIndex > 0u) { - _SEGGER_RTT.aDown[BufferIndex].sName = sName; - _SEGGER_RTT.aDown[BufferIndex].pBuffer = pBuffer; - _SEGGER_RTT.aDown[BufferIndex].SizeOfBuffer = BufferSize; - _SEGGER_RTT.aDown[BufferIndex].RdOff = 0u; - _SEGGER_RTT.aDown[BufferIndex].WrOff = 0u; - } - _SEGGER_RTT.aDown[BufferIndex].Flags = Flags; - SEGGER_RTT_UNLOCK(); - r = 0; - } else { - r = -1; - } - return r; -} - -/********************************************************************* -* -* SEGGER_RTT_SetNameUpBuffer -* -* Function description -* Run-time configuration of a specific up-buffer name (T->H). -* Buffer to be configured is specified by index. -* -* Parameters -* BufferIndex Index of the buffer to renamed. -* sName Pointer to a constant name string. -* -* Return value -* >= 0 O.K. -* < 0 Error -*/ -int SEGGER_RTT_SetNameUpBuffer(unsigned BufferIndex, const char* sName) { - int r; - - INIT(); - if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumUpBuffers) { - SEGGER_RTT_LOCK(); - _SEGGER_RTT.aUp[BufferIndex].sName = sName; - SEGGER_RTT_UNLOCK(); - r = 0; - } else { - r = -1; - } - return r; -} - -/********************************************************************* -* -* SEGGER_RTT_SetNameDownBuffer -* -* Function description -* Run-time configuration of a specific Down-buffer name (T->H). -* Buffer to be configured is specified by index. -* -* Parameters -* BufferIndex Index of the buffer to renamed. -* sName Pointer to a constant name string. -* -* Return value -* >= 0 O.K. -* < 0 Error -*/ -int SEGGER_RTT_SetNameDownBuffer(unsigned BufferIndex, const char* sName) { - int r; - - INIT(); - if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumDownBuffers) { - SEGGER_RTT_LOCK(); - _SEGGER_RTT.aDown[BufferIndex].sName = sName; - SEGGER_RTT_UNLOCK(); - r = 0; - } else { - r = -1; - } - return r; -} - -/********************************************************************* -* -* SEGGER_RTT_Init -* -* Function description -* Initializes the RTT Control Block. -* Should be used in RAM targets, at start of the application. -* -*/ -void SEGGER_RTT_Init (void) { - _DoInit(); -} - -/********************************************************************* -* -* SEGGER_RTT_SetTerminal -* -* Function description -* Sets the terminal to be used for output on channel 0. -* -* Parameters -* TerminalId Index of the terminal. -* -* Return value -* >= 0 O.K. -* < 0 Error (e.g. if RTT is configured for non-blocking mode and there was no space in the buffer to set the new terminal Id) -*/ -int SEGGER_RTT_SetTerminal (char TerminalId) { - char ac[2]; - SEGGER_RTT_BUFFER_UP* pRing; - unsigned Avail; - int r; - // - INIT(); - // - r = 0; - ac[0] = 0xFFU; - if ((unsigned char)TerminalId < (unsigned char)sizeof(_aTerminalId)) { // We only support a certain number of channels - ac[1] = _aTerminalId[(unsigned char)TerminalId]; - pRing = &_SEGGER_RTT.aUp[0]; // Buffer 0 is always reserved for terminal I/O, so we can use index 0 here, fixed - SEGGER_RTT_LOCK(); // Lock to make sure that no other task is writing into buffer, while we are and number of free bytes in buffer does not change downwards after checking and before writing - if ((pRing->Flags & SEGGER_RTT_MODE_MASK) == SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL) { - _ActiveTerminal = TerminalId; - _WriteBlocking(pRing, ac, 2u); - } else { // Skipping mode or trim mode? => We cannot trim this command so handling is the same for both modes - Avail = _GetAvailWriteSpace(pRing); - if (Avail >= 2) { - _ActiveTerminal = TerminalId; // Only change active terminal in case of success - _WriteNoCheck(pRing, ac, 2u); - } else { - r = -1; - } - } - SEGGER_RTT_UNLOCK(); - } else { - r = -1; - } - return r; -} - -/********************************************************************* -* -* SEGGER_RTT_TerminalOut -* -* Function description -* Writes a string to the given terminal -* without changing the terminal for channel 0. -* -* Parameters -* TerminalId Index of the terminal. -* s String to be printed on the terminal. -* -* Return value -* >= 0 - Number of bytes written. -* < 0 - Error. -* -*/ -int SEGGER_RTT_TerminalOut (char TerminalId, const char* s) { - int Status; - unsigned FragLen; - unsigned Avail; - SEGGER_RTT_BUFFER_UP* pRing; - // - INIT(); - // - // Validate terminal ID. - // - if (TerminalId < (char)sizeof(_aTerminalId)) { // We only support a certain number of channels - // - // Get "to-host" ring buffer. - // - pRing = &_SEGGER_RTT.aUp[0]; - // - // Need to be able to change terminal, write data, change back. - // Compute the fixed and variable sizes. - // - FragLen = strlen(s); - // - // How we output depends upon the mode... - // - SEGGER_RTT_LOCK(); - Avail = _GetAvailWriteSpace(pRing); - switch (pRing->Flags & SEGGER_RTT_MODE_MASK) { - case SEGGER_RTT_MODE_NO_BLOCK_SKIP: - // - // If we are in skip mode and there is no space for the whole - // of this output, don't bother switching terminals at all. - // - if (Avail < (FragLen + 4u)) { - Status = 0; - } else { - _PostTerminalSwitch(pRing, TerminalId); - Status = (int)_WriteBlocking(pRing, s, FragLen); - _PostTerminalSwitch(pRing, _ActiveTerminal); - } - break; - case SEGGER_RTT_MODE_NO_BLOCK_TRIM: - // - // If we are in trim mode and there is not enough space for everything, - // trim the output but always include the terminal switch. If no room - // for terminal switch, skip that totally. - // - if (Avail < 4u) { - Status = -1; - } else { - _PostTerminalSwitch(pRing, TerminalId); - Status = (int)_WriteBlocking(pRing, s, (FragLen < (Avail - 4u)) ? FragLen : (Avail - 4u)); - _PostTerminalSwitch(pRing, _ActiveTerminal); - } - break; - case SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL: - // - // If we are in blocking mode, output everything. - // - _PostTerminalSwitch(pRing, TerminalId); - Status = (int)_WriteBlocking(pRing, s, FragLen); - _PostTerminalSwitch(pRing, _ActiveTerminal); - break; - default: - Status = -1; - break; - } - // - // Finish up. - // - SEGGER_RTT_UNLOCK(); - } else { - Status = -1; - } - return Status; -} - - -/*************************** End of file ****************************/ diff --git a/examples/device/nrf52840_freertos/segger/SEGGER_RTT.h b/examples/device/nrf52840_freertos/segger/SEGGER_RTT.h deleted file mode 100644 index d3cac44dd..000000000 --- a/examples/device/nrf52840_freertos/segger/SEGGER_RTT.h +++ /dev/null @@ -1,234 +0,0 @@ -/********************************************************************* -* SEGGER MICROCONTROLLER GmbH & Co. KG * -* Solutions for real time microcontroller applications * -********************************************************************** -* * -* (c) 2014 - 2016 SEGGER Microcontroller GmbH & Co. KG * -* * -* www.segger.com Support: support@segger.com * -* * -********************************************************************** -* * -* SEGGER RTT * Real Time Transfer for embedded targets * -* * -********************************************************************** -* * -* All rights reserved. * -* * -* * This software may in its unmodified form be freely redistributed * -* in source form. * -* * The source code may be modified, provided the source code * -* retains the above copyright notice, this list of conditions and * -* the following disclaimer. * -* * Modified versions of this software in source or linkable form * -* may not be distributed without prior consent of SEGGER. * -* * This software may only be used for communication with SEGGER * -* J-Link debug probes. * -* * -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * -* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * -* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * -* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * -* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR * -* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * -* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * -* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * -* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * -* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * -* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * -* DAMAGE. * -* * -********************************************************************** -* * -* RTT version: 5.12e * -* * -********************************************************************** ----------------------------END-OF-HEADER------------------------------ -File : SEGGER_RTT.h -Purpose : Implementation of SEGGER real-time transfer which allows - real-time communication on targets which support debugger - memory accesses while the CPU is running. ----------------------------------------------------------------------- -*/ - -#ifndef SEGGER_RTT_H -#define SEGGER_RTT_H - -#include "SEGGER_RTT_Conf.h" - -/********************************************************************* -* -* Defines, fixed -* -********************************************************************** -*/ - -/********************************************************************* -* -* Types -* -********************************************************************** -*/ - -// -// Description for a circular buffer (also called "ring buffer") -// which is used as up-buffer (T->H) -// -typedef struct { - const char* sName; // Optional name. Standard names so far are: "Terminal", "SysView", "J-Scope_t4i4" - char* pBuffer; // Pointer to start of buffer - unsigned SizeOfBuffer; // Buffer size in bytes. Note that one byte is lost, as this implementation does not fill up the buffer in order to avoid the problem of being unable to distinguish between full and empty. - unsigned WrOff; // Position of next item to be written by either target. - volatile unsigned RdOff; // Position of next item to be read by host. Must be volatile since it may be modified by host. - unsigned Flags; // Contains configuration flags -} SEGGER_RTT_BUFFER_UP; - -// -// Description for a circular buffer (also called "ring buffer") -// which is used as down-buffer (H->T) -// -typedef struct { - const char* sName; // Optional name. Standard names so far are: "Terminal", "SysView", "J-Scope_t4i4" - char* pBuffer; // Pointer to start of buffer - unsigned SizeOfBuffer; // Buffer size in bytes. Note that one byte is lost, as this implementation does not fill up the buffer in order to avoid the problem of being unable to distinguish between full and empty. - volatile unsigned WrOff; // Position of next item to be written by host. Must be volatile since it may be modified by host. - unsigned RdOff; // Position of next item to be read by target (down-buffer). - unsigned Flags; // Contains configuration flags -} SEGGER_RTT_BUFFER_DOWN; - -// -// RTT control block which describes the number of buffers available -// as well as the configuration for each buffer -// -// -typedef struct { - char acID[16]; // Initialized to "SEGGER RTT" - int MaxNumUpBuffers; // Initialized to SEGGER_RTT_MAX_NUM_UP_BUFFERS (type. 2) - int MaxNumDownBuffers; // Initialized to SEGGER_RTT_MAX_NUM_DOWN_BUFFERS (type. 2) - SEGGER_RTT_BUFFER_UP aUp[SEGGER_RTT_MAX_NUM_UP_BUFFERS]; // Up buffers, transferring information up from target via debug probe to host - SEGGER_RTT_BUFFER_DOWN aDown[SEGGER_RTT_MAX_NUM_DOWN_BUFFERS]; // Down buffers, transferring information down from host via debug probe to target -} SEGGER_RTT_CB; - -/********************************************************************* -* -* Global data -* -********************************************************************** -*/ -extern SEGGER_RTT_CB _SEGGER_RTT; - -/********************************************************************* -* -* RTT API functions -* -********************************************************************** -*/ -#ifdef __cplusplus - extern "C" { -#endif -int SEGGER_RTT_AllocDownBuffer (const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags); -int SEGGER_RTT_AllocUpBuffer (const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags); -int SEGGER_RTT_ConfigUpBuffer (unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags); -int SEGGER_RTT_ConfigDownBuffer (unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags); -int SEGGER_RTT_GetKey (void); -unsigned SEGGER_RTT_HasData (unsigned BufferIndex); -int SEGGER_RTT_HasKey (void); -void SEGGER_RTT_Init (void); -unsigned SEGGER_RTT_Read (unsigned BufferIndex, void* pBuffer, unsigned BufferSize); -unsigned SEGGER_RTT_ReadNoLock (unsigned BufferIndex, void* pData, unsigned BufferSize); -int SEGGER_RTT_SetNameDownBuffer(unsigned BufferIndex, const char* sName); -int SEGGER_RTT_SetNameUpBuffer (unsigned BufferIndex, const char* sName); -int SEGGER_RTT_WaitKey (void); -unsigned SEGGER_RTT_Write (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes); -unsigned SEGGER_RTT_WriteNoLock (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes); -unsigned SEGGER_RTT_WriteSkipNoLock (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes); -unsigned SEGGER_RTT_WriteString (unsigned BufferIndex, const char* s); -void SEGGER_RTT_WriteWithOverwriteNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes); -// -// Function macro for performance optimization -// -#define SEGGER_RTT_HASDATA(n) (_SEGGER_RTT.aDown[n].WrOff - _SEGGER_RTT.aDown[n].RdOff) - -/********************************************************************* -* -* RTT "Terminal" API functions -* -********************************************************************** -*/ -int SEGGER_RTT_SetTerminal (char TerminalId); -int SEGGER_RTT_TerminalOut (char TerminalId, const char* s); - -/********************************************************************* -* -* RTT printf functions (require SEGGER_RTT_printf.c) -* -********************************************************************** -*/ -int SEGGER_RTT_printf(unsigned BufferIndex, const char * sFormat, ...); -#ifdef __cplusplus - } -#endif - -/********************************************************************* -* -* Defines -* -********************************************************************** -*/ - -// -// Operating modes. Define behavior if buffer is full (not enough space for entire message) -// -#define SEGGER_RTT_MODE_NO_BLOCK_SKIP (0U) // Skip. Do not block, output nothing. (Default) -#define SEGGER_RTT_MODE_NO_BLOCK_TRIM (1U) // Trim: Do not block, output as much as fits. -#define SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL (2U) // Block: Wait until there is space in the buffer. -#define SEGGER_RTT_MODE_MASK (3U) - -// -// Control sequences, based on ANSI. -// Can be used to control color, and clear the screen -// -#define RTT_CTRL_RESET "" // Reset to default colors -#define RTT_CTRL_CLEAR "" // Clear screen, reposition cursor to top left - -#define RTT_CTRL_TEXT_BLACK "" -#define RTT_CTRL_TEXT_RED "" -#define RTT_CTRL_TEXT_GREEN "" -#define RTT_CTRL_TEXT_YELLOW "" -#define RTT_CTRL_TEXT_BLUE "" -#define RTT_CTRL_TEXT_MAGENTA "" -#define RTT_CTRL_TEXT_CYAN "" -#define RTT_CTRL_TEXT_WHITE "" - -#define RTT_CTRL_TEXT_BRIGHT_BLACK "" -#define RTT_CTRL_TEXT_BRIGHT_RED "" -#define RTT_CTRL_TEXT_BRIGHT_GREEN "" -#define RTT_CTRL_TEXT_BRIGHT_YELLOW "" -#define RTT_CTRL_TEXT_BRIGHT_BLUE "" -#define RTT_CTRL_TEXT_BRIGHT_MAGENTA "" -#define RTT_CTRL_TEXT_BRIGHT_CYAN "" -#define RTT_CTRL_TEXT_BRIGHT_WHITE "" - -#define RTT_CTRL_BG_BLACK "" -#define RTT_CTRL_BG_RED "" -#define RTT_CTRL_BG_GREEN "" -#define RTT_CTRL_BG_YELLOW "" -#define RTT_CTRL_BG_BLUE "" -#define RTT_CTRL_BG_MAGENTA "" -#define RTT_CTRL_BG_CYAN "" -#define RTT_CTRL_BG_WHITE "" - -#define RTT_CTRL_BG_BRIGHT_BLACK "" -#define RTT_CTRL_BG_BRIGHT_RED "" -#define RTT_CTRL_BG_BRIGHT_GREEN "" -#define RTT_CTRL_BG_BRIGHT_YELLOW "" -#define RTT_CTRL_BG_BRIGHT_BLUE "" -#define RTT_CTRL_BG_BRIGHT_MAGENTA "" -#define RTT_CTRL_BG_BRIGHT_CYAN "" -#define RTT_CTRL_BG_BRIGHT_WHITE "" - - -#endif - -/*************************** End of file ****************************/ diff --git a/examples/device/nrf52840_freertos/segger/SEGGER_RTT_Conf.h b/examples/device/nrf52840_freertos/segger/SEGGER_RTT_Conf.h deleted file mode 100644 index aef3b4053..000000000 --- a/examples/device/nrf52840_freertos/segger/SEGGER_RTT_Conf.h +++ /dev/null @@ -1,242 +0,0 @@ -/********************************************************************* -* SEGGER MICROCONTROLLER GmbH & Co. KG * -* Solutions for real time microcontroller applications * -********************************************************************** -* * -* (c) 2014 - 2016 SEGGER Microcontroller GmbH & Co. KG * -* * -* www.segger.com Support: support@segger.com * -* * -********************************************************************** -* * -* SEGGER RTT * Real Time Transfer for embedded targets * -* * -********************************************************************** -* * -* All rights reserved. * -* * -* * This software may in its unmodified form be freely redistributed * -* in source form. * -* * The source code may be modified, provided the source code * -* retains the above copyright notice, this list of conditions and * -* the following disclaimer. * -* * Modified versions of this software in source or linkable form * -* may not be distributed without prior consent of SEGGER. * -* * This software may only be used for communication with SEGGER * -* J-Link debug probes. * -* * -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * -* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * -* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * -* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * -* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR * -* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * -* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * -* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * -* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * -* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * -* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * -* DAMAGE. * -* * -********************************************************************** -* * -* RTT version: 5.12e * -* * -********************************************************************** ----------------------------------------------------------------------- -File : SEGGER_RTT_Conf.h -Purpose : Implementation of SEGGER real-time transfer (RTT) which - allows real-time communication on targets which support - debugger memory accesses while the CPU is running. ----------------------------END-OF-HEADER------------------------------ -*/ - -#ifndef SEGGER_RTT_CONF_H -#define SEGGER_RTT_CONF_H - -#ifdef __ICCARM__ - #include -#endif - -/********************************************************************* -* -* Defines, configurable -* -********************************************************************** -*/ - -#define SEGGER_RTT_MAX_NUM_UP_BUFFERS (2) // Max. number of up-buffers (T->H) available on this target (Default: 2) -#define SEGGER_RTT_MAX_NUM_DOWN_BUFFERS (2) // Max. number of down-buffers (H->T) available on this target (Default: 2) - -#define BUFFER_SIZE_UP (1024) // Size of the buffer for terminal output of target, up to host (Default: 1k) -#define BUFFER_SIZE_DOWN (16) // Size of the buffer for terminal input to target from host (Usually keyboard input) (Default: 16) - -#define SEGGER_RTT_PRINTF_BUFFER_SIZE (64u) // Size of buffer for RTT printf to bulk-send chars via RTT (Default: 64) - -#define SEGGER_RTT_MODE_DEFAULT SEGGER_RTT_MODE_NO_BLOCK_SKIP // Mode for pre-initialized terminal channel (buffer 0) - -// -// Target is not allowed to perform other RTT operations while string still has not been stored completely. -// Otherwise we would probably end up with a mixed string in the buffer. -// If using RTT from within interrupts, multiple tasks or multi processors, define the SEGGER_RTT_LOCK() and SEGGER_RTT_UNLOCK() function here. -// -// SEGGER_RTT_MAX_INTERRUPT_PRIORITY can be used in the sample lock routines on Cortex-M3/4. -// Make sure to mask all interrupts which can send RTT data, i.e. generate SystemView events, or cause task switches. -// When high-priority interrupts must not be masked while sending RTT data, SEGGER_RTT_MAX_INTERRUPT_PRIORITY needs to be adjusted accordingly. -// (Higher priority = lower priority number) -// Default value for embOS: 128u -// Default configuration in FreeRTOS: configMAX_SYSCALL_INTERRUPT_PRIORITY: ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) ) -// In case of doubt mask all interrupts: 0u -// - -#define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20) // Interrupt priority to lock on SEGGER_RTT_LOCK on Cortex-M3/4 (Default: 0x20) - -/********************************************************************* -* -* RTT lock configuration for SEGGER Embedded Studio, -* Rowley CrossStudio and GCC -*/ -#if (defined __SES_ARM) || (defined __CROSSWORKS_ARM) || (defined __GNUC__) - #ifdef __ARM_ARCH_6M__ - #define SEGGER_RTT_LOCK() { \ - unsigned int LockState; \ - __asm volatile ("mrs %0, primask \n\t" \ - "mov r1, $1 \n\t" \ - "msr primask, r1 \n\t" \ - : "=r" (LockState) \ - : \ - : "r1" \ - ); - - #define SEGGER_RTT_UNLOCK() __asm volatile ("msr primask, %0 \n\t" \ - : \ - : "r" (LockState) \ - : \ - ); \ - } - - #elif (defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)) - #ifndef SEGGER_RTT_MAX_INTERRUPT_PRIORITY - #define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20) - #endif - #define SEGGER_RTT_LOCK() { \ - unsigned int LockState; \ - __asm volatile ("mrs %0, basepri \n\t" \ - "mov r1, %1 \n\t" \ - "msr basepri, r1 \n\t" \ - : "=r" (LockState) \ - : "i"(SEGGER_RTT_MAX_INTERRUPT_PRIORITY) \ - : "r1" \ - ); - - #define SEGGER_RTT_UNLOCK() __asm volatile ("msr basepri, %0 \n\t" \ - : \ - : "r" (LockState) \ - : \ - ); \ - } - - #elif defined(__ARM_ARCH_7A__) - #define SEGGER_RTT_LOCK() { \ - unsigned int LockState; \ - __asm volatile ("mrs r1, CPSR \n\t" \ - "mov %0, r1 \n\t" \ - "orr r1, r1, #0xC0 \n\t" \ - "msr CPSR_c, r1 \n\t" \ - : "=r" (LockState) \ - : \ - : "r1" \ - ); - - #define SEGGER_RTT_UNLOCK() __asm volatile ("mov r0, %0 \n\t" \ - "mrs r1, CPSR \n\t" \ - "bic r1, r1, #0xC0 \n\t" \ - "and r0, r0, #0xC0 \n\t" \ - "orr r1, r1, r0 \n\t" \ - "msr CPSR_c, r1 \n\t" \ - : \ - : "r" (LockState) \ - : "r0", "r1" \ - ); \ - } -#else - #define SEGGER_RTT_LOCK() - #define SEGGER_RTT_UNLOCK() - #endif -#endif - -/********************************************************************* -* -* RTT lock configuration for IAR EWARM -*/ -#ifdef __ICCARM__ - #if (defined (__ARM6M__) && (__CORE__ == __ARM6M__)) - #define SEGGER_RTT_LOCK() { \ - unsigned int LockState; \ - LockState = __get_PRIMASK(); \ - __set_PRIMASK(1); - - #define SEGGER_RTT_UNLOCK() __set_PRIMASK(LockState); \ - } - #elif ((defined (__ARM7EM__) && (__CORE__ == __ARM7EM__)) || (defined (__ARM7M__) && (__CORE__ == __ARM7M__))) - #ifndef SEGGER_RTT_MAX_INTERRUPT_PRIORITY - #define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20) - #endif - #define SEGGER_RTT_LOCK() { \ - unsigned int LockState; \ - LockState = __get_BASEPRI(); \ - __set_BASEPRI(SEGGER_RTT_MAX_INTERRUPT_PRIORITY); - - #define SEGGER_RTT_UNLOCK() __set_BASEPRI(LockState); \ - } - #endif -#endif - -/********************************************************************* -* -* RTT lock configuration for KEIL ARM -*/ -#ifdef __CC_ARM - #if (defined __TARGET_ARCH_6S_M) - #define SEGGER_RTT_LOCK() { \ - unsigned int LockState; \ - register unsigned char PRIMASK __asm( "primask"); \ - LockState = PRIMASK; \ - PRIMASK = 1u; \ - __schedule_barrier(); - - #define SEGGER_RTT_UNLOCK() PRIMASK = LockState; \ - __schedule_barrier(); \ - } - #elif (defined(__TARGET_ARCH_7_M) || defined(__TARGET_ARCH_7E_M)) - #ifndef SEGGER_RTT_MAX_INTERRUPT_PRIORITY - #define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20) - #endif - #define SEGGER_RTT_LOCK() { \ - unsigned int LockState; \ - register unsigned char BASEPRI __asm( "basepri"); \ - LockState = BASEPRI; \ - BASEPRI = SEGGER_RTT_MAX_INTERRUPT_PRIORITY; \ - __schedule_barrier(); - - #define SEGGER_RTT_UNLOCK() BASEPRI = LockState; \ - __schedule_barrier(); \ - } - #endif -#endif - -/********************************************************************* -* -* RTT lock configuration fallback -*/ -#ifndef SEGGER_RTT_LOCK - #define SEGGER_RTT_LOCK() // Lock RTT (nestable) (i.e. disable interrupts) -#endif - -#ifndef SEGGER_RTT_UNLOCK - #define SEGGER_RTT_UNLOCK() // Unlock RTT (nestable) (i.e. enable previous interrupt lock state) -#endif - -#endif -/*************************** End of file ****************************/ diff --git a/examples/device/nrf52840_freertos/segger/SEGGER_RTT_SES.c b/examples/device/nrf52840_freertos/segger/SEGGER_RTT_SES.c deleted file mode 100644 index e6634147c..000000000 --- a/examples/device/nrf52840_freertos/segger/SEGGER_RTT_SES.c +++ /dev/null @@ -1,76 +0,0 @@ -/********************************************************************* -* SEGGER MICROCONTROLLER GmbH & Co. KG * -* Solutions for real time microcontroller applications * -********************************************************************** -* * -* (c) 2014 - 2015 SEGGER Microcontroller GmbH & Co. KG * -* * -* www.segger.com Support: support@segger.com * -* * -********************************************************************** -* * -* All rights reserved. * -* * -* * This software may in its unmodified form be freely redistributed * -* in source form. * -* * The source code may be modified, provided the source code * -* retains the above copyright notice, this list of conditions and * -* the following disclaimer. * -* * Modified versions of this software in source or linkable form * -* may not be distributed without prior consent of SEGGER. * -* * This software may only be used for communication with SEGGER * -* J-Link debug probes. * -* * -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * -* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * -* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * -* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * -* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR * -* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * -* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * -* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * -* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * -* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * -* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * -* DAMAGE. * -* * -********************************************************************** --------- END-OF-HEADER --------------------------------------------- -File : SEGGER_RTT_Syscalls_SES.c -Purpose : Reimplementation of printf, puts and - implementation of __putchar and __getchar using RTT in SES. - To use RTT for printf output, include this file in your - application. ----------------------------------------------------------------------- -*/ -#include "SEGGER_RTT.h" -#include "__libc.h" -#include -#include - -int printf(const char *fmt,...) { - char buffer[128]; - va_list args; - va_start (args, fmt); - int n = vsnprintf(buffer, sizeof(buffer), fmt, args); - SEGGER_RTT_Write(0, buffer, n); - va_end(args); - return n; -} - -int puts(const char *s) { - return SEGGER_RTT_WriteString(0, s); -} - -int __putchar(int x, __printf_tag_ptr ctx) { - (void)ctx; - SEGGER_RTT_Write(0, (char *)&x, 1); - return x; -} - -int __getchar() { - return SEGGER_RTT_WaitKey(); -} - -/****** End Of File *************************************************/ diff --git a/examples/device/nrf52840_freertos/segger/nrf5x_freertos.emProject b/examples/device/nrf52840_freertos/segger/nrf5x_freertos.emProject index f01207bab..661dc12a6 100644 --- a/examples/device/nrf52840_freertos/segger/nrf5x_freertos.emProject +++ b/examples/device/nrf52840_freertos/segger/nrf5x_freertos.emProject @@ -32,12 +32,6 @@ target_reset_script="Reset();" target_script_file="$(ProjectDir)/nRF_Target.js" target_trace_initialize_script="EnableTrace("$(TraceInterfaceType)")" /> - - - - - - @@ -60,6 +54,12 @@ + + + + + + diff --git a/examples/device/nrf52840_freertos/src/main.c b/examples/device/nrf52840_freertos/src/main.c index 6fb76a84d..d5a5d0c2c 100644 --- a/examples/device/nrf52840_freertos/src/main.c +++ b/examples/device/nrf52840_freertos/src/main.c @@ -101,18 +101,32 @@ void cdc_task(void* params) while ( 1 ) { // connected and there are data available - if ( tud_mounted() && tud_cdc_available() ) + if ( tud_cdc_connected() ) { - uint8_t buf[64]; + if ( tud_cdc_available() ) + { + uint8_t buf[64]; + + // read and echo back + uint32_t count = tud_cdc_read(buf, sizeof(buf)); - // read and echo back - uint32_t count = tud_cdc_read(buf, sizeof(buf)); + tud_cdc_write(buf, count); + } - tud_cdc_write(buf, count); tud_cdc_write_flush(); } + } +} + +void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts) +{ + (void) itf; - taskYIELD(); + // connected + if ( dtr && rts ) + { + // print greeting + tud_cdc_write_str("tinyusb usb cdc\n"); } } #endif diff --git a/examples/device/nrf52840_freertos/src/segger_rtt/SEGGER_RTT.c b/examples/device/nrf52840_freertos/src/segger_rtt/SEGGER_RTT.c new file mode 100644 index 000000000..aee5bd21e --- /dev/null +++ b/examples/device/nrf52840_freertos/src/segger_rtt/SEGGER_RTT.c @@ -0,0 +1,1329 @@ +/********************************************************************* +* SEGGER MICROCONTROLLER GmbH & Co. KG * +* Solutions for real time microcontroller applications * +********************************************************************** +* * +* (c) 2014 - 2016 SEGGER Microcontroller GmbH & Co. KG * +* * +* www.segger.com Support: support@segger.com * +* * +********************************************************************** +* * +* SEGGER RTT * Real Time Transfer for embedded targets * +* * +********************************************************************** +* * +* All rights reserved. * +* * +* * This software may in its unmodified form be freely redistributed * +* in source form. * +* * The source code may be modified, provided the source code * +* retains the above copyright notice, this list of conditions and * +* the following disclaimer. * +* * Modified versions of this software in source or linkable form * +* may not be distributed without prior consent of SEGGER. * +* * This software may only be used for communication with SEGGER * +* J-Link debug probes. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * +* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * +* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * +* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * +* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * +* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * +* DAMAGE. * +* * +********************************************************************** +* * +* RTT version: 5.12e * +* * +********************************************************************** +---------------------------END-OF-HEADER------------------------------ +File : SEGGER_RTT.c +Purpose : Implementation of SEGGER real-time transfer (RTT) which + allows real-time communication on targets which support + debugger memory accesses while the CPU is running. + +Additional information: + Type "int" is assumed to be 32-bits in size + H->T Host to target communication + T->H Target to host communication + + RTT channel 0 is always present and reserved for Terminal usage. + Name is fixed to "Terminal" + + Effective buffer size: SizeOfBuffer - 1 + + WrOff == RdOff: Buffer is empty + WrOff == (RdOff - 1): Buffer is full + WrOff > RdOff: Free space includes wrap-around + WrOff < RdOff: Used space includes wrap-around + (WrOff == (SizeOfBuffer - 1)) && (RdOff == 0): + Buffer full and wrap-around after next byte + + +---------------------------------------------------------------------- +*/ + +#include "SEGGER_RTT.h" + +#include // for memcpy + +/********************************************************************* +* +* Configuration, default values +* +********************************************************************** +*/ + +#ifndef BUFFER_SIZE_UP + #define BUFFER_SIZE_UP 1024 // Size of the buffer for terminal output of target, up to host +#endif + +#ifndef BUFFER_SIZE_DOWN + #define BUFFER_SIZE_DOWN 16 // Size of the buffer for terminal input to target from host (Usually keyboard input) +#endif + +#ifndef SEGGER_RTT_MAX_NUM_UP_BUFFERS + #define SEGGER_RTT_MAX_NUM_UP_BUFFERS 2 // Number of up-buffers (T->H) available on this target +#endif + +#ifndef SEGGER_RTT_MAX_NUM_DOWN_BUFFERS + #define SEGGER_RTT_MAX_NUM_DOWN_BUFFERS 2 // Number of down-buffers (H->T) available on this target +#endif + +#ifndef SEGGER_RTT_BUFFER_SECTION + #if defined SEGGER_RTT_SECTION + #define SEGGER_RTT_BUFFER_SECTION SEGGER_RTT_SECTION + #endif +#endif + +#ifndef SEGGER_RTT_MODE_DEFAULT + #define SEGGER_RTT_MODE_DEFAULT SEGGER_RTT_MODE_NO_BLOCK_SKIP +#endif + +#ifndef SEGGER_RTT_LOCK + #define SEGGER_RTT_LOCK() +#endif + +#ifndef SEGGER_RTT_UNLOCK + #define SEGGER_RTT_UNLOCK() +#endif + +#ifndef STRLEN + #define STRLEN(a) strlen((a)) +#endif + +#ifndef MEMCPY + #define MEMCPY(pDest, pSrc, NumBytes) memcpy((pDest), (pSrc), (NumBytes)) +#endif + +#ifndef MIN + #define MIN(a, b) (((a) < (b)) ? (a) : (b)) +#endif + +#ifndef MAX + #define MAX(a, b) (((a) > (b)) ? (a) : (b)) +#endif +// +// For some environments, NULL may not be defined until certain headers are included +// +#ifndef NULL + #define NULL 0 +#endif + +/********************************************************************* +* +* Static const data +* +********************************************************************** +*/ + +static unsigned char _aTerminalId[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; + +/********************************************************************* +* +* Static data +* +********************************************************************** +*/ +// +// RTT Control Block and allocate buffers for channel 0 +// +#ifdef SEGGER_RTT_SECTION + #if (defined __GNUC__) + __attribute__ ((section (SEGGER_RTT_SECTION))) SEGGER_RTT_CB _SEGGER_RTT; + #elif (defined __ICCARM__) || (defined __ICCRX__) + #pragma location=SEGGER_RTT_SECTION + SEGGER_RTT_CB _SEGGER_RTT; + #elif (defined __CC_ARM__) + __attribute__ ((section (SEGGER_RTT_SECTION), zero_init)) SEGGER_RTT_CB _SEGGER_RTT; + #else + SEGGER_RTT_CB _SEGGER_RTT; + #endif +#else + SEGGER_RTT_CB _SEGGER_RTT; +#endif + +#ifdef SEGGER_RTT_BUFFER_SECTION + #if (defined __GNUC__) + __attribute__ ((section (SEGGER_RTT_BUFFER_SECTION))) static char _acUpBuffer [BUFFER_SIZE_UP]; + __attribute__ ((section (SEGGER_RTT_BUFFER_SECTION))) static char _acDownBuffer[BUFFER_SIZE_DOWN]; + #elif (defined __ICCARM__) || (defined __ICCRX__) + #pragma location=SEGGER_RTT_BUFFER_SECTION + static char _acUpBuffer [BUFFER_SIZE_UP]; + #pragma location=SEGGER_RTT_BUFFER_SECTION + static char _acDownBuffer[BUFFER_SIZE_DOWN]; + #elif (defined __CC_ARM__) + __attribute__ ((section (SEGGER_RTT_BUFFER_SECTION), zero_init)) static char _acUpBuffer [BUFFER_SIZE_UP]; + __attribute__ ((section (SEGGER_RTT_BUFFER_SECTION), zero_init)) static char _acDownBuffer[BUFFER_SIZE_DOWN]; + #else + static char _acUpBuffer [BUFFER_SIZE_UP]; + static char _acDownBuffer[BUFFER_SIZE_DOWN]; + #endif +#else + static char _acUpBuffer [BUFFER_SIZE_UP]; + static char _acDownBuffer[BUFFER_SIZE_DOWN]; +#endif + +static char _ActiveTerminal; + +/********************************************************************* +* +* Static functions +* +********************************************************************** +*/ + +/********************************************************************* +* +* _DoInit() +* +* Function description +* Initializes the control block an buffers. +* May only be called via INIT() to avoid overriding settings. +* +*/ +#define INIT() do { \ + if (_SEGGER_RTT.acID[0] == '\0') { _DoInit(); } \ + } while (0) +static void _DoInit(void) { + SEGGER_RTT_CB* p; + // + // Initialize control block + // + p = &_SEGGER_RTT; + p->MaxNumUpBuffers = SEGGER_RTT_MAX_NUM_UP_BUFFERS; + p->MaxNumDownBuffers = SEGGER_RTT_MAX_NUM_DOWN_BUFFERS; + // + // Initialize up buffer 0 + // + p->aUp[0].sName = "Terminal"; + p->aUp[0].pBuffer = _acUpBuffer; + p->aUp[0].SizeOfBuffer = sizeof(_acUpBuffer); + p->aUp[0].RdOff = 0u; + p->aUp[0].WrOff = 0u; + p->aUp[0].Flags = SEGGER_RTT_MODE_DEFAULT; + // + // Initialize down buffer 0 + // + p->aDown[0].sName = "Terminal"; + p->aDown[0].pBuffer = _acDownBuffer; + p->aDown[0].SizeOfBuffer = sizeof(_acDownBuffer); + p->aDown[0].RdOff = 0u; + p->aDown[0].WrOff = 0u; + p->aDown[0].Flags = SEGGER_RTT_MODE_DEFAULT; + // + // Finish initialization of the control block. + // Copy Id string in three steps to make sure "SEGGER RTT" is not found + // in initializer memory (usually flash) by J-Link + // + strcpy(&p->acID[7], "RTT"); + strcpy(&p->acID[0], "SEGGER"); + p->acID[6] = ' '; +} + +/********************************************************************* +* +* _WriteBlocking() +* +* Function description +* Stores a specified number of characters in SEGGER RTT ring buffer +* and updates the associated write pointer which is periodically +* read by the host. +* The caller is responsible for managing the write chunk sizes as +* _WriteBlocking() will block until all data has been posted successfully. +* +* Parameters +* pRing Ring buffer to post to. +* pBuffer Pointer to character array. Does not need to point to a \0 terminated string. +* NumBytes Number of bytes to be stored in the SEGGER RTT control block. +* +* Return value +* >= 0 - Number of bytes written into buffer. +*/ +static unsigned _WriteBlocking(SEGGER_RTT_BUFFER_UP* pRing, const char* pBuffer, unsigned NumBytes) { + unsigned NumBytesToWrite; + unsigned NumBytesWritten; + unsigned RdOff; + unsigned WrOff; + // + // Write data to buffer and handle wrap-around if necessary + // + NumBytesWritten = 0u; + WrOff = pRing->WrOff; + do { + RdOff = pRing->RdOff; // May be changed by host (debug probe) in the meantime + if (RdOff > WrOff) { + NumBytesToWrite = RdOff - WrOff - 1u; + } else { + NumBytesToWrite = pRing->SizeOfBuffer - (WrOff - RdOff + 1u); + } + NumBytesToWrite = MIN(NumBytesToWrite, (pRing->SizeOfBuffer - WrOff)); // Number of bytes that can be written until buffer wrap-around + NumBytesToWrite = MIN(NumBytesToWrite, NumBytes); + memcpy(pRing->pBuffer + WrOff, pBuffer, NumBytesToWrite); + NumBytesWritten += NumBytesToWrite; + pBuffer += NumBytesToWrite; + NumBytes -= NumBytesToWrite; + WrOff += NumBytesToWrite; + if (WrOff == pRing->SizeOfBuffer) { + WrOff = 0u; + } + pRing->WrOff = WrOff; + } while (NumBytes); + // + return NumBytesWritten; +} + +/********************************************************************* +* +* _WriteNoCheck() +* +* Function description +* Stores a specified number of characters in SEGGER RTT ring buffer +* and updates the associated write pointer which is periodically +* read by the host. +* It is callers responsibility to make sure data actually fits in buffer. +* +* Parameters +* pRing Ring buffer to post to. +* pBuffer Pointer to character array. Does not need to point to a \0 terminated string. +* NumBytes Number of bytes to be stored in the SEGGER RTT control block. +* +* Notes +* (1) If there might not be enough space in the "Up"-buffer, call _WriteBlocking +*/ +static void _WriteNoCheck(SEGGER_RTT_BUFFER_UP* pRing, const char* pData, unsigned NumBytes) { + unsigned NumBytesAtOnce; + unsigned WrOff; + unsigned Rem; + + WrOff = pRing->WrOff; + Rem = pRing->SizeOfBuffer - WrOff; + if (Rem > NumBytes) { + // + // All data fits before wrap around + // + memcpy(pRing->pBuffer + WrOff, pData, NumBytes); + pRing->WrOff = WrOff + NumBytes; + } else { + // + // We reach the end of the buffer, so need to wrap around + // + NumBytesAtOnce = Rem; + memcpy(pRing->pBuffer + WrOff, pData, NumBytesAtOnce); + NumBytesAtOnce = NumBytes - Rem; + memcpy(pRing->pBuffer, pData + Rem, NumBytesAtOnce); + pRing->WrOff = NumBytesAtOnce; + } +} + +/********************************************************************* +* +* _PostTerminalSwitch() +* +* Function description +* Switch terminal to the given terminal ID. It is the caller's +* responsibility to ensure the terminal ID is correct and there is +* enough space in the buffer for this to complete successfully. +* +* Parameters +* pRing Ring buffer to post to. +* TerminalId Terminal ID to switch to. +*/ +static void _PostTerminalSwitch(SEGGER_RTT_BUFFER_UP* pRing, unsigned char TerminalId) { + char ac[2]; + + ac[0] = 0xFFu; + ac[1] = _aTerminalId[TerminalId]; // Caller made already sure that TerminalId does not exceed our terminal limit + _WriteBlocking(pRing, ac, 2u); +} + +/********************************************************************* +* +* _GetAvailWriteSpace() +* +* Function description +* Returns the number of bytes that can be written to the ring +* buffer without blocking. +* +* Parameters +* pRing Ring buffer to check. +* +* Return value +* Number of bytes that are free in the buffer. +*/ +static unsigned _GetAvailWriteSpace(SEGGER_RTT_BUFFER_UP* pRing) { + unsigned RdOff; + unsigned WrOff; + unsigned r; + // + // Avoid warnings regarding volatile access order. It's not a problem + // in this case, but dampen compiler enthusiasm. + // + RdOff = pRing->RdOff; + WrOff = pRing->WrOff; + if (RdOff <= WrOff) { + r = pRing->SizeOfBuffer - 1u - WrOff + RdOff; + } else { + r = RdOff - WrOff - 1u; + } + return r; +} + +/********************************************************************* +* +* Public code +* +********************************************************************** +*/ +/********************************************************************* +* +* SEGGER_RTT_ReadNoLock() +* +* Function description +* Reads characters from SEGGER real-time-terminal control block +* which have been previously stored by the host. +* Do not lock against interrupts and multiple access. +* +* Parameters +* BufferIndex Index of Down-buffer to be used (e.g. 0 for "Terminal"). +* pBuffer Pointer to buffer provided by target application, to copy characters from RTT-down-buffer to. +* BufferSize Size of the target application buffer. +* +* Return value +* Number of bytes that have been read. +*/ +unsigned SEGGER_RTT_ReadNoLock(unsigned BufferIndex, void* pData, unsigned BufferSize) { + unsigned NumBytesRem; + unsigned NumBytesRead; + unsigned RdOff; + unsigned WrOff; + unsigned char* pBuffer; + SEGGER_RTT_BUFFER_DOWN* pRing; + // + INIT(); + pRing = &_SEGGER_RTT.aDown[BufferIndex]; + pBuffer = (unsigned char*)pData; + RdOff = pRing->RdOff; + WrOff = pRing->WrOff; + NumBytesRead = 0u; + // + // Read from current read position to wrap-around of buffer, first + // + if (RdOff > WrOff) { + NumBytesRem = pRing->SizeOfBuffer - RdOff; + NumBytesRem = MIN(NumBytesRem, BufferSize); + memcpy(pBuffer, pRing->pBuffer + RdOff, NumBytesRem); + NumBytesRead += NumBytesRem; + pBuffer += NumBytesRem; + BufferSize -= NumBytesRem; + RdOff += NumBytesRem; + // + // Handle wrap-around of buffer + // + if (RdOff == pRing->SizeOfBuffer) { + RdOff = 0u; + } + } + // + // Read remaining items of buffer + // + NumBytesRem = WrOff - RdOff; + NumBytesRem = MIN(NumBytesRem, BufferSize); + if (NumBytesRem > 0u) { + memcpy(pBuffer, pRing->pBuffer + RdOff, NumBytesRem); + NumBytesRead += NumBytesRem; + pBuffer += NumBytesRem; + BufferSize -= NumBytesRem; + RdOff += NumBytesRem; + } + if (NumBytesRead) { + pRing->RdOff = RdOff; + } + // + return NumBytesRead; +} + +/********************************************************************* +* +* SEGGER_RTT_Read +* +* Function description +* Reads characters from SEGGER real-time-terminal control block +* which have been previously stored by the host. +* +* Parameters +* BufferIndex Index of Down-buffer to be used (e.g. 0 for "Terminal"). +* pBuffer Pointer to buffer provided by target application, to copy characters from RTT-down-buffer to. +* BufferSize Size of the target application buffer. +* +* Return value +* Number of bytes that have been read. +*/ +unsigned SEGGER_RTT_Read(unsigned BufferIndex, void* pBuffer, unsigned BufferSize) { + unsigned NumBytesRead; + // + SEGGER_RTT_LOCK(); + // + // Call the non-locking read function + // + NumBytesRead = SEGGER_RTT_ReadNoLock(BufferIndex, pBuffer, BufferSize); + // + // Finish up. + // + SEGGER_RTT_UNLOCK(); + // + return NumBytesRead; +} + +/********************************************************************* +* +* SEGGER_RTT_WriteWithOverwriteNoLock +* +* Function description +* Stores a specified number of characters in SEGGER RTT +* control block. +* SEGGER_RTT_WriteWithOverwriteNoLock does not lock the application +* and overwrites data if the data does not fit into the buffer. +* +* Parameters +* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). +* pBuffer Pointer to character array. Does not need to point to a \0 terminated string. +* NumBytes Number of bytes to be stored in the SEGGER RTT control block. +* +* Notes +* (1) If there is not enough space in the "Up"-buffer, data is overwritten. +* (2) For performance reasons this function does not call Init() +* and may only be called after RTT has been initialized. +* Either by calling SEGGER_RTT_Init() or calling another RTT API function first. +* (3) Do not use SEGGER_RTT_WriteWithOverwriteNoLock if a J-Link +* connection reads RTT data. +*/ +void SEGGER_RTT_WriteWithOverwriteNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) { + const char* pData; + SEGGER_RTT_BUFFER_UP* pRing; + unsigned Avail; + + pData = (const char *)pBuffer; + // + // Get "to-host" ring buffer and copy some elements into local variables. + // + pRing = &_SEGGER_RTT.aUp[BufferIndex]; + // + // Check if we will overwrite data and need to adjust the RdOff. + // + if (pRing->WrOff == pRing->RdOff) { + Avail = pRing->SizeOfBuffer - 1u; + } else if ( pRing->WrOff < pRing->RdOff) { + Avail = pRing->RdOff - pRing->WrOff - 1u; + } else { + Avail = pRing->RdOff - pRing->WrOff - 1u + pRing->SizeOfBuffer; + } + if (NumBytes > Avail) { + pRing->RdOff += (NumBytes - Avail); + while (pRing->RdOff >= pRing->SizeOfBuffer) { + pRing->RdOff -= pRing->SizeOfBuffer; + } + } + // + // Write all data, no need to check the RdOff, but possibly handle multiple wrap-arounds + // + Avail = pRing->SizeOfBuffer - pRing->WrOff; + do { + if (Avail > NumBytes) { + // + // Last round + // +#if 1 // memcpy() is good for large amounts of data, but the overhead is too big for small amounts. Use a simple byte loop instead. + char* pDst; + pDst = pRing->pBuffer + pRing->WrOff; + pRing->WrOff += NumBytes; + do { + *pDst++ = *pData++; + } while (--NumBytes); +#else + memcpy(pRing->pBuffer + WrOff, pData, NumBytes); + pRing->WrOff += NumBytes; +#endif + break; //Alternatively: NumBytes = 0; + } else { + // + // Wrap-around necessary, write until wrap-around and reset WrOff + // + memcpy(pRing->pBuffer + pRing->WrOff, pData, Avail); + pData += Avail; + pRing->WrOff = 0; + NumBytes -= Avail; + Avail = (pRing->SizeOfBuffer - 1); + } + } while (NumBytes); +} + +/********************************************************************* +* +* SEGGER_RTT_WriteSkipNoLock +* +* Function description +* Stores a specified number of characters in SEGGER RTT +* control block which is then read by the host. +* SEGGER_RTT_WriteSkipNoLock does not lock the application and +* skips all data, if the data does not fit into the buffer. +* +* Parameters +* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). +* pBuffer Pointer to character array. Does not need to point to a \0 terminated string. +* NumBytes Number of bytes to be stored in the SEGGER RTT control block. +* +* Return value +* Number of bytes which have been stored in the "Up"-buffer. +* +* Notes +* (1) If there is not enough space in the "Up"-buffer, all data is dropped. +* (2) For performance reasons this function does not call Init() +* and may only be called after RTT has been initialized. +* Either by calling SEGGER_RTT_Init() or calling another RTT API function first. +*/ +unsigned SEGGER_RTT_WriteSkipNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) { + const char* pData; + SEGGER_RTT_BUFFER_UP* pRing; + unsigned Avail; + unsigned RdOff; + unsigned WrOff; + unsigned Rem; + + pData = (const char *)pBuffer; + // + // Get "to-host" ring buffer and copy some elements into local variables. + // + pRing = &_SEGGER_RTT.aUp[BufferIndex]; + RdOff = pRing->RdOff; + WrOff = pRing->WrOff; + // + // Handle the most common cases fastest. + // Which is: + // RdOff <= WrOff -> Space until wrap around is free. + // AND + // WrOff + NumBytes < SizeOfBuffer -> No Wrap around necessary. + // + // OR + // + // RdOff > WrOff -> Space until RdOff - 1 is free. + // AND + // WrOff + NumBytes < RdOff -> Data fits into buffer + // + if (RdOff <= WrOff) { + // + // Get space until WrOff will be at wrap around. + // + Avail = pRing->SizeOfBuffer - 1u - WrOff ; + if (Avail >= NumBytes) { +#if 1 // memcpy() is good for large amounts of data, but the overhead is too big for small amounts. Use a simple byte loop instead. + char* pDst; + pDst = pRing->pBuffer + WrOff; + WrOff += NumBytes; + do { + *pDst++ = *pData++; + } while (--NumBytes); + pRing->WrOff = WrOff + NumBytes; +#else + memcpy(pRing->pBuffer + WrOff, pData, NumBytes); + pRing->WrOff = WrOff + NumBytes; +#endif + return 1; + } + // + // If data did not fit into space until wrap around calculate complete space in buffer. + // + Avail += RdOff; + // + // If there is still no space for the whole of this output, don't bother. + // + if (Avail >= NumBytes) { + // + // OK, we have enough space in buffer. Copy in one or 2 chunks + // + Rem = pRing->SizeOfBuffer - WrOff; // Space until end of buffer + if (Rem > NumBytes) { + memcpy(pRing->pBuffer + WrOff, pData, NumBytes); + pRing->WrOff = WrOff + NumBytes; + } else { + // + // We reach the end of the buffer, so need to wrap around + // + memcpy(pRing->pBuffer + WrOff, pData, Rem); + memcpy(pRing->pBuffer, pData + Rem, NumBytes - Rem); + pRing->WrOff = NumBytes - Rem; + } + return 1; + } + } else { + Avail = RdOff - WrOff - 1u; + if (Avail >= NumBytes) { + memcpy(pRing->pBuffer + WrOff, pData, NumBytes); + pRing->WrOff = WrOff + NumBytes; + return 1; + } + } + // + // If we reach this point no data has been written + // + return 0; +} + +/********************************************************************* +* +* SEGGER_RTT_WriteNoLock +* +* Function description +* Stores a specified number of characters in SEGGER RTT +* control block which is then read by the host. +* SEGGER_RTT_WriteNoLock does not lock the application. +* +* Parameters +* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). +* pBuffer Pointer to character array. Does not need to point to a \0 terminated string. +* NumBytes Number of bytes to be stored in the SEGGER RTT control block. +* +* Return value +* Number of bytes which have been stored in the "Up"-buffer. +* +* Notes +* (1) If there is not enough space in the "Up"-buffer, remaining characters of pBuffer are dropped. +* (2) For performance reasons this function does not call Init() +* and may only be called after RTT has been initialized. +* Either by calling SEGGER_RTT_Init() or calling another RTT API function first. +*/ +unsigned SEGGER_RTT_WriteNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) { + unsigned Status; + unsigned Avail; + const char* pData; + SEGGER_RTT_BUFFER_UP* pRing; + + pData = (const char *)pBuffer; + // + // Get "to-host" ring buffer. + // + pRing = &_SEGGER_RTT.aUp[BufferIndex]; + // + // How we output depends upon the mode... + // + switch (pRing->Flags) { + case SEGGER_RTT_MODE_NO_BLOCK_SKIP: + // + // If we are in skip mode and there is no space for the whole + // of this output, don't bother. + // + Avail = _GetAvailWriteSpace(pRing); + if (Avail < NumBytes) { + Status = 0u; + } else { + Status = NumBytes; + _WriteNoCheck(pRing, pData, NumBytes); + } + break; + case SEGGER_RTT_MODE_NO_BLOCK_TRIM: + // + // If we are in trim mode, trim to what we can output without blocking. + // + Avail = _GetAvailWriteSpace(pRing); + Status = Avail < NumBytes ? Avail : NumBytes; + _WriteNoCheck(pRing, pData, Status); + break; + case SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL: + // + // If we are in blocking mode, output everything. + // + Status = _WriteBlocking(pRing, pData, NumBytes); + break; + default: + Status = 0u; + break; + } + // + // Finish up. + // + return Status; +} + +/********************************************************************* +* +* SEGGER_RTT_Write +* +* Function description +* Stores a specified number of characters in SEGGER RTT +* control block which is then read by the host. +* +* Parameters +* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). +* pBuffer Pointer to character array. Does not need to point to a \0 terminated string. +* NumBytes Number of bytes to be stored in the SEGGER RTT control block. +* +* Return value +* Number of bytes which have been stored in the "Up"-buffer. +* +* Notes +* (1) If there is not enough space in the "Up"-buffer, remaining characters of pBuffer are dropped. +*/ +unsigned SEGGER_RTT_Write(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) { + unsigned Status; + // + INIT(); + SEGGER_RTT_LOCK(); + // + // Call the non-locking write function + // + Status = SEGGER_RTT_WriteNoLock(BufferIndex, pBuffer, NumBytes); + // + // Finish up. + // + SEGGER_RTT_UNLOCK(); + // + return Status; +} + +/********************************************************************* +* +* SEGGER_RTT_WriteString +* +* Function description +* Stores string in SEGGER RTT control block. +* This data is read by the host. +* +* Parameters +* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). +* s Pointer to string. +* +* Return value +* Number of bytes which have been stored in the "Up"-buffer. +* +* Notes +* (1) If there is not enough space in the "Up"-buffer, depending on configuration, +* remaining characters may be dropped or RTT module waits until there is more space in the buffer. +* (2) String passed to this function has to be \0 terminated +* (3) \0 termination character is *not* stored in RTT buffer +*/ +unsigned SEGGER_RTT_WriteString(unsigned BufferIndex, const char* s) { + unsigned Len; + + Len = STRLEN(s); + return SEGGER_RTT_Write(BufferIndex, s, Len); +} + +/********************************************************************* +* +* SEGGER_RTT_GetKey +* +* Function description +* Reads one character from the SEGGER RTT buffer. +* Host has previously stored data there. +* +* Return value +* < 0 - No character available (buffer empty). +* >= 0 - Character which has been read. (Possible values: 0 - 255) +* +* Notes +* (1) This function is only specified for accesses to RTT buffer 0. +*/ +int SEGGER_RTT_GetKey(void) { + char c; + int r; + + r = (int)SEGGER_RTT_Read(0u, &c, 1u); + if (r == 1) { + r = (int)(unsigned char)c; + } else { + r = -1; + } + return r; +} + +/********************************************************************* +* +* SEGGER_RTT_WaitKey +* +* Function description +* Waits until at least one character is avaible in the SEGGER RTT buffer. +* Once a character is available, it is read and this function returns. +* +* Return value +* >=0 - Character which has been read. +* +* Notes +* (1) This function is only specified for accesses to RTT buffer 0 +* (2) This function is blocking if no character is present in RTT buffer +*/ +int SEGGER_RTT_WaitKey(void) { + int r; + + do { + r = SEGGER_RTT_GetKey(); + } while (r < 0); + return r; +} + +/********************************************************************* +* +* SEGGER_RTT_HasKey +* +* Function description +* Checks if at least one character for reading is available in the SEGGER RTT buffer. +* +* Return value +* == 0 - No characters are available to read. +* == 1 - At least one character is available. +* +* Notes +* (1) This function is only specified for accesses to RTT buffer 0 +*/ +int SEGGER_RTT_HasKey(void) { + unsigned RdOff; + int r; + + INIT(); + RdOff = _SEGGER_RTT.aDown[0].RdOff; + if (RdOff != _SEGGER_RTT.aDown[0].WrOff) { + r = 1; + } else { + r = 0; + } + return r; +} + +/********************************************************************* +* +* SEGGER_RTT_HasData +* +* Function description +* Check if there is data from the host in the given buffer. +* +* Return value: +* ==0: No data +* !=0: Data in buffer +* +*/ +unsigned SEGGER_RTT_HasData(unsigned BufferIndex) { + SEGGER_RTT_BUFFER_DOWN* pRing; + unsigned v; + + pRing = &_SEGGER_RTT.aDown[BufferIndex]; + v = pRing->WrOff; + return v - pRing->RdOff; +} + +/********************************************************************* +* +* SEGGER_RTT_AllocDownBuffer +* +* Function description +* Run-time configuration of the next down-buffer (H->T). +* The next buffer, which is not used yet is configured. +* This includes: Buffer address, size, name, flags, ... +* +* Parameters +* sName Pointer to a constant name string. +* pBuffer Pointer to a buffer to be used. +* BufferSize Size of the buffer. +* Flags Operating modes. Define behavior if buffer is full (not enough space for entire message). +* +* Return value +* >= 0 - O.K. Buffer Index +* < 0 - Error +*/ +int SEGGER_RTT_AllocDownBuffer(const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) { + int BufferIndex; + + INIT(); + SEGGER_RTT_LOCK(); + BufferIndex = 0; + do { + if (_SEGGER_RTT.aDown[BufferIndex].pBuffer == NULL) { + break; + } + BufferIndex++; + } while (BufferIndex < _SEGGER_RTT.MaxNumDownBuffers); + if (BufferIndex < _SEGGER_RTT.MaxNumDownBuffers) { + _SEGGER_RTT.aDown[BufferIndex].sName = sName; + _SEGGER_RTT.aDown[BufferIndex].pBuffer = pBuffer; + _SEGGER_RTT.aDown[BufferIndex].SizeOfBuffer = BufferSize; + _SEGGER_RTT.aDown[BufferIndex].RdOff = 0u; + _SEGGER_RTT.aDown[BufferIndex].WrOff = 0u; + _SEGGER_RTT.aDown[BufferIndex].Flags = Flags; + } else { + BufferIndex = -1; + } + SEGGER_RTT_UNLOCK(); + return BufferIndex; +} + +/********************************************************************* +* +* SEGGER_RTT_AllocUpBuffer +* +* Function description +* Run-time configuration of the next up-buffer (T->H). +* The next buffer, which is not used yet is configured. +* This includes: Buffer address, size, name, flags, ... +* +* Parameters +* sName Pointer to a constant name string. +* pBuffer Pointer to a buffer to be used. +* BufferSize Size of the buffer. +* Flags Operating modes. Define behavior if buffer is full (not enough space for entire message). +* +* Return value +* >= 0 - O.K. Buffer Index +* < 0 - Error +*/ +int SEGGER_RTT_AllocUpBuffer(const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) { + int BufferIndex; + + INIT(); + SEGGER_RTT_LOCK(); + BufferIndex = 0; + do { + if (_SEGGER_RTT.aUp[BufferIndex].pBuffer == NULL) { + break; + } + BufferIndex++; + } while (BufferIndex < _SEGGER_RTT.MaxNumUpBuffers); + if (BufferIndex < _SEGGER_RTT.MaxNumUpBuffers) { + _SEGGER_RTT.aUp[BufferIndex].sName = sName; + _SEGGER_RTT.aUp[BufferIndex].pBuffer = pBuffer; + _SEGGER_RTT.aUp[BufferIndex].SizeOfBuffer = BufferSize; + _SEGGER_RTT.aUp[BufferIndex].RdOff = 0u; + _SEGGER_RTT.aUp[BufferIndex].WrOff = 0u; + _SEGGER_RTT.aUp[BufferIndex].Flags = Flags; + } else { + BufferIndex = -1; + } + SEGGER_RTT_UNLOCK(); + return BufferIndex; +} + +/********************************************************************* +* +* SEGGER_RTT_ConfigUpBuffer +* +* Function description +* Run-time configuration of a specific up-buffer (T->H). +* Buffer to be configured is specified by index. +* This includes: Buffer address, size, name, flags, ... +* +* Parameters +* BufferIndex Index of the buffer to configure. +* sName Pointer to a constant name string. +* pBuffer Pointer to a buffer to be used. +* BufferSize Size of the buffer. +* Flags Operating modes. Define behavior if buffer is full (not enough space for entire message). +* +* Return value +* >= 0 - O.K. +* < 0 - Error +*/ +int SEGGER_RTT_ConfigUpBuffer(unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) { + int r; + + INIT(); + if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumUpBuffers) { + SEGGER_RTT_LOCK(); + if (BufferIndex > 0u) { + _SEGGER_RTT.aUp[BufferIndex].sName = sName; + _SEGGER_RTT.aUp[BufferIndex].pBuffer = pBuffer; + _SEGGER_RTT.aUp[BufferIndex].SizeOfBuffer = BufferSize; + _SEGGER_RTT.aUp[BufferIndex].RdOff = 0u; + _SEGGER_RTT.aUp[BufferIndex].WrOff = 0u; + } + _SEGGER_RTT.aUp[BufferIndex].Flags = Flags; + SEGGER_RTT_UNLOCK(); + r = 0; + } else { + r = -1; + } + return r; +} + +/********************************************************************* +* +* SEGGER_RTT_ConfigDownBuffer +* +* Function description +* Run-time configuration of a specific down-buffer (H->T). +* Buffer to be configured is specified by index. +* This includes: Buffer address, size, name, flags, ... +* +* Parameters +* BufferIndex Index of the buffer to configure. +* sName Pointer to a constant name string. +* pBuffer Pointer to a buffer to be used. +* BufferSize Size of the buffer. +* Flags Operating modes. Define behavior if buffer is full (not enough space for entire message). +* +* Return value +* >= 0 O.K. +* < 0 Error +*/ +int SEGGER_RTT_ConfigDownBuffer(unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) { + int r; + + INIT(); + if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumDownBuffers) { + SEGGER_RTT_LOCK(); + if (BufferIndex > 0u) { + _SEGGER_RTT.aDown[BufferIndex].sName = sName; + _SEGGER_RTT.aDown[BufferIndex].pBuffer = pBuffer; + _SEGGER_RTT.aDown[BufferIndex].SizeOfBuffer = BufferSize; + _SEGGER_RTT.aDown[BufferIndex].RdOff = 0u; + _SEGGER_RTT.aDown[BufferIndex].WrOff = 0u; + } + _SEGGER_RTT.aDown[BufferIndex].Flags = Flags; + SEGGER_RTT_UNLOCK(); + r = 0; + } else { + r = -1; + } + return r; +} + +/********************************************************************* +* +* SEGGER_RTT_SetNameUpBuffer +* +* Function description +* Run-time configuration of a specific up-buffer name (T->H). +* Buffer to be configured is specified by index. +* +* Parameters +* BufferIndex Index of the buffer to renamed. +* sName Pointer to a constant name string. +* +* Return value +* >= 0 O.K. +* < 0 Error +*/ +int SEGGER_RTT_SetNameUpBuffer(unsigned BufferIndex, const char* sName) { + int r; + + INIT(); + if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumUpBuffers) { + SEGGER_RTT_LOCK(); + _SEGGER_RTT.aUp[BufferIndex].sName = sName; + SEGGER_RTT_UNLOCK(); + r = 0; + } else { + r = -1; + } + return r; +} + +/********************************************************************* +* +* SEGGER_RTT_SetNameDownBuffer +* +* Function description +* Run-time configuration of a specific Down-buffer name (T->H). +* Buffer to be configured is specified by index. +* +* Parameters +* BufferIndex Index of the buffer to renamed. +* sName Pointer to a constant name string. +* +* Return value +* >= 0 O.K. +* < 0 Error +*/ +int SEGGER_RTT_SetNameDownBuffer(unsigned BufferIndex, const char* sName) { + int r; + + INIT(); + if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumDownBuffers) { + SEGGER_RTT_LOCK(); + _SEGGER_RTT.aDown[BufferIndex].sName = sName; + SEGGER_RTT_UNLOCK(); + r = 0; + } else { + r = -1; + } + return r; +} + +/********************************************************************* +* +* SEGGER_RTT_Init +* +* Function description +* Initializes the RTT Control Block. +* Should be used in RAM targets, at start of the application. +* +*/ +void SEGGER_RTT_Init (void) { + _DoInit(); +} + +/********************************************************************* +* +* SEGGER_RTT_SetTerminal +* +* Function description +* Sets the terminal to be used for output on channel 0. +* +* Parameters +* TerminalId Index of the terminal. +* +* Return value +* >= 0 O.K. +* < 0 Error (e.g. if RTT is configured for non-blocking mode and there was no space in the buffer to set the new terminal Id) +*/ +int SEGGER_RTT_SetTerminal (char TerminalId) { + char ac[2]; + SEGGER_RTT_BUFFER_UP* pRing; + unsigned Avail; + int r; + // + INIT(); + // + r = 0; + ac[0] = 0xFFU; + if ((unsigned char)TerminalId < (unsigned char)sizeof(_aTerminalId)) { // We only support a certain number of channels + ac[1] = _aTerminalId[(unsigned char)TerminalId]; + pRing = &_SEGGER_RTT.aUp[0]; // Buffer 0 is always reserved for terminal I/O, so we can use index 0 here, fixed + SEGGER_RTT_LOCK(); // Lock to make sure that no other task is writing into buffer, while we are and number of free bytes in buffer does not change downwards after checking and before writing + if ((pRing->Flags & SEGGER_RTT_MODE_MASK) == SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL) { + _ActiveTerminal = TerminalId; + _WriteBlocking(pRing, ac, 2u); + } else { // Skipping mode or trim mode? => We cannot trim this command so handling is the same for both modes + Avail = _GetAvailWriteSpace(pRing); + if (Avail >= 2) { + _ActiveTerminal = TerminalId; // Only change active terminal in case of success + _WriteNoCheck(pRing, ac, 2u); + } else { + r = -1; + } + } + SEGGER_RTT_UNLOCK(); + } else { + r = -1; + } + return r; +} + +/********************************************************************* +* +* SEGGER_RTT_TerminalOut +* +* Function description +* Writes a string to the given terminal +* without changing the terminal for channel 0. +* +* Parameters +* TerminalId Index of the terminal. +* s String to be printed on the terminal. +* +* Return value +* >= 0 - Number of bytes written. +* < 0 - Error. +* +*/ +int SEGGER_RTT_TerminalOut (char TerminalId, const char* s) { + int Status; + unsigned FragLen; + unsigned Avail; + SEGGER_RTT_BUFFER_UP* pRing; + // + INIT(); + // + // Validate terminal ID. + // + if (TerminalId < (char)sizeof(_aTerminalId)) { // We only support a certain number of channels + // + // Get "to-host" ring buffer. + // + pRing = &_SEGGER_RTT.aUp[0]; + // + // Need to be able to change terminal, write data, change back. + // Compute the fixed and variable sizes. + // + FragLen = strlen(s); + // + // How we output depends upon the mode... + // + SEGGER_RTT_LOCK(); + Avail = _GetAvailWriteSpace(pRing); + switch (pRing->Flags & SEGGER_RTT_MODE_MASK) { + case SEGGER_RTT_MODE_NO_BLOCK_SKIP: + // + // If we are in skip mode and there is no space for the whole + // of this output, don't bother switching terminals at all. + // + if (Avail < (FragLen + 4u)) { + Status = 0; + } else { + _PostTerminalSwitch(pRing, TerminalId); + Status = (int)_WriteBlocking(pRing, s, FragLen); + _PostTerminalSwitch(pRing, _ActiveTerminal); + } + break; + case SEGGER_RTT_MODE_NO_BLOCK_TRIM: + // + // If we are in trim mode and there is not enough space for everything, + // trim the output but always include the terminal switch. If no room + // for terminal switch, skip that totally. + // + if (Avail < 4u) { + Status = -1; + } else { + _PostTerminalSwitch(pRing, TerminalId); + Status = (int)_WriteBlocking(pRing, s, (FragLen < (Avail - 4u)) ? FragLen : (Avail - 4u)); + _PostTerminalSwitch(pRing, _ActiveTerminal); + } + break; + case SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL: + // + // If we are in blocking mode, output everything. + // + _PostTerminalSwitch(pRing, TerminalId); + Status = (int)_WriteBlocking(pRing, s, FragLen); + _PostTerminalSwitch(pRing, _ActiveTerminal); + break; + default: + Status = -1; + break; + } + // + // Finish up. + // + SEGGER_RTT_UNLOCK(); + } else { + Status = -1; + } + return Status; +} + + +/*************************** End of file ****************************/ diff --git a/examples/device/nrf52840_freertos/src/segger_rtt/SEGGER_RTT.h b/examples/device/nrf52840_freertos/src/segger_rtt/SEGGER_RTT.h new file mode 100644 index 000000000..d3cac44dd --- /dev/null +++ b/examples/device/nrf52840_freertos/src/segger_rtt/SEGGER_RTT.h @@ -0,0 +1,234 @@ +/********************************************************************* +* SEGGER MICROCONTROLLER GmbH & Co. KG * +* Solutions for real time microcontroller applications * +********************************************************************** +* * +* (c) 2014 - 2016 SEGGER Microcontroller GmbH & Co. KG * +* * +* www.segger.com Support: support@segger.com * +* * +********************************************************************** +* * +* SEGGER RTT * Real Time Transfer for embedded targets * +* * +********************************************************************** +* * +* All rights reserved. * +* * +* * This software may in its unmodified form be freely redistributed * +* in source form. * +* * The source code may be modified, provided the source code * +* retains the above copyright notice, this list of conditions and * +* the following disclaimer. * +* * Modified versions of this software in source or linkable form * +* may not be distributed without prior consent of SEGGER. * +* * This software may only be used for communication with SEGGER * +* J-Link debug probes. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * +* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * +* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * +* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * +* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * +* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * +* DAMAGE. * +* * +********************************************************************** +* * +* RTT version: 5.12e * +* * +********************************************************************** +---------------------------END-OF-HEADER------------------------------ +File : SEGGER_RTT.h +Purpose : Implementation of SEGGER real-time transfer which allows + real-time communication on targets which support debugger + memory accesses while the CPU is running. +---------------------------------------------------------------------- +*/ + +#ifndef SEGGER_RTT_H +#define SEGGER_RTT_H + +#include "SEGGER_RTT_Conf.h" + +/********************************************************************* +* +* Defines, fixed +* +********************************************************************** +*/ + +/********************************************************************* +* +* Types +* +********************************************************************** +*/ + +// +// Description for a circular buffer (also called "ring buffer") +// which is used as up-buffer (T->H) +// +typedef struct { + const char* sName; // Optional name. Standard names so far are: "Terminal", "SysView", "J-Scope_t4i4" + char* pBuffer; // Pointer to start of buffer + unsigned SizeOfBuffer; // Buffer size in bytes. Note that one byte is lost, as this implementation does not fill up the buffer in order to avoid the problem of being unable to distinguish between full and empty. + unsigned WrOff; // Position of next item to be written by either target. + volatile unsigned RdOff; // Position of next item to be read by host. Must be volatile since it may be modified by host. + unsigned Flags; // Contains configuration flags +} SEGGER_RTT_BUFFER_UP; + +// +// Description for a circular buffer (also called "ring buffer") +// which is used as down-buffer (H->T) +// +typedef struct { + const char* sName; // Optional name. Standard names so far are: "Terminal", "SysView", "J-Scope_t4i4" + char* pBuffer; // Pointer to start of buffer + unsigned SizeOfBuffer; // Buffer size in bytes. Note that one byte is lost, as this implementation does not fill up the buffer in order to avoid the problem of being unable to distinguish between full and empty. + volatile unsigned WrOff; // Position of next item to be written by host. Must be volatile since it may be modified by host. + unsigned RdOff; // Position of next item to be read by target (down-buffer). + unsigned Flags; // Contains configuration flags +} SEGGER_RTT_BUFFER_DOWN; + +// +// RTT control block which describes the number of buffers available +// as well as the configuration for each buffer +// +// +typedef struct { + char acID[16]; // Initialized to "SEGGER RTT" + int MaxNumUpBuffers; // Initialized to SEGGER_RTT_MAX_NUM_UP_BUFFERS (type. 2) + int MaxNumDownBuffers; // Initialized to SEGGER_RTT_MAX_NUM_DOWN_BUFFERS (type. 2) + SEGGER_RTT_BUFFER_UP aUp[SEGGER_RTT_MAX_NUM_UP_BUFFERS]; // Up buffers, transferring information up from target via debug probe to host + SEGGER_RTT_BUFFER_DOWN aDown[SEGGER_RTT_MAX_NUM_DOWN_BUFFERS]; // Down buffers, transferring information down from host via debug probe to target +} SEGGER_RTT_CB; + +/********************************************************************* +* +* Global data +* +********************************************************************** +*/ +extern SEGGER_RTT_CB _SEGGER_RTT; + +/********************************************************************* +* +* RTT API functions +* +********************************************************************** +*/ +#ifdef __cplusplus + extern "C" { +#endif +int SEGGER_RTT_AllocDownBuffer (const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags); +int SEGGER_RTT_AllocUpBuffer (const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags); +int SEGGER_RTT_ConfigUpBuffer (unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags); +int SEGGER_RTT_ConfigDownBuffer (unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags); +int SEGGER_RTT_GetKey (void); +unsigned SEGGER_RTT_HasData (unsigned BufferIndex); +int SEGGER_RTT_HasKey (void); +void SEGGER_RTT_Init (void); +unsigned SEGGER_RTT_Read (unsigned BufferIndex, void* pBuffer, unsigned BufferSize); +unsigned SEGGER_RTT_ReadNoLock (unsigned BufferIndex, void* pData, unsigned BufferSize); +int SEGGER_RTT_SetNameDownBuffer(unsigned BufferIndex, const char* sName); +int SEGGER_RTT_SetNameUpBuffer (unsigned BufferIndex, const char* sName); +int SEGGER_RTT_WaitKey (void); +unsigned SEGGER_RTT_Write (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes); +unsigned SEGGER_RTT_WriteNoLock (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes); +unsigned SEGGER_RTT_WriteSkipNoLock (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes); +unsigned SEGGER_RTT_WriteString (unsigned BufferIndex, const char* s); +void SEGGER_RTT_WriteWithOverwriteNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes); +// +// Function macro for performance optimization +// +#define SEGGER_RTT_HASDATA(n) (_SEGGER_RTT.aDown[n].WrOff - _SEGGER_RTT.aDown[n].RdOff) + +/********************************************************************* +* +* RTT "Terminal" API functions +* +********************************************************************** +*/ +int SEGGER_RTT_SetTerminal (char TerminalId); +int SEGGER_RTT_TerminalOut (char TerminalId, const char* s); + +/********************************************************************* +* +* RTT printf functions (require SEGGER_RTT_printf.c) +* +********************************************************************** +*/ +int SEGGER_RTT_printf(unsigned BufferIndex, const char * sFormat, ...); +#ifdef __cplusplus + } +#endif + +/********************************************************************* +* +* Defines +* +********************************************************************** +*/ + +// +// Operating modes. Define behavior if buffer is full (not enough space for entire message) +// +#define SEGGER_RTT_MODE_NO_BLOCK_SKIP (0U) // Skip. Do not block, output nothing. (Default) +#define SEGGER_RTT_MODE_NO_BLOCK_TRIM (1U) // Trim: Do not block, output as much as fits. +#define SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL (2U) // Block: Wait until there is space in the buffer. +#define SEGGER_RTT_MODE_MASK (3U) + +// +// Control sequences, based on ANSI. +// Can be used to control color, and clear the screen +// +#define RTT_CTRL_RESET "" // Reset to default colors +#define RTT_CTRL_CLEAR "" // Clear screen, reposition cursor to top left + +#define RTT_CTRL_TEXT_BLACK "" +#define RTT_CTRL_TEXT_RED "" +#define RTT_CTRL_TEXT_GREEN "" +#define RTT_CTRL_TEXT_YELLOW "" +#define RTT_CTRL_TEXT_BLUE "" +#define RTT_CTRL_TEXT_MAGENTA "" +#define RTT_CTRL_TEXT_CYAN "" +#define RTT_CTRL_TEXT_WHITE "" + +#define RTT_CTRL_TEXT_BRIGHT_BLACK "" +#define RTT_CTRL_TEXT_BRIGHT_RED "" +#define RTT_CTRL_TEXT_BRIGHT_GREEN "" +#define RTT_CTRL_TEXT_BRIGHT_YELLOW "" +#define RTT_CTRL_TEXT_BRIGHT_BLUE "" +#define RTT_CTRL_TEXT_BRIGHT_MAGENTA "" +#define RTT_CTRL_TEXT_BRIGHT_CYAN "" +#define RTT_CTRL_TEXT_BRIGHT_WHITE "" + +#define RTT_CTRL_BG_BLACK "" +#define RTT_CTRL_BG_RED "" +#define RTT_CTRL_BG_GREEN "" +#define RTT_CTRL_BG_YELLOW "" +#define RTT_CTRL_BG_BLUE "" +#define RTT_CTRL_BG_MAGENTA "" +#define RTT_CTRL_BG_CYAN "" +#define RTT_CTRL_BG_WHITE "" + +#define RTT_CTRL_BG_BRIGHT_BLACK "" +#define RTT_CTRL_BG_BRIGHT_RED "" +#define RTT_CTRL_BG_BRIGHT_GREEN "" +#define RTT_CTRL_BG_BRIGHT_YELLOW "" +#define RTT_CTRL_BG_BRIGHT_BLUE "" +#define RTT_CTRL_BG_BRIGHT_MAGENTA "" +#define RTT_CTRL_BG_BRIGHT_CYAN "" +#define RTT_CTRL_BG_BRIGHT_WHITE "" + + +#endif + +/*************************** End of file ****************************/ diff --git a/examples/device/nrf52840_freertos/src/segger_rtt/SEGGER_RTT_Conf.h b/examples/device/nrf52840_freertos/src/segger_rtt/SEGGER_RTT_Conf.h new file mode 100644 index 000000000..aef3b4053 --- /dev/null +++ b/examples/device/nrf52840_freertos/src/segger_rtt/SEGGER_RTT_Conf.h @@ -0,0 +1,242 @@ +/********************************************************************* +* SEGGER MICROCONTROLLER GmbH & Co. KG * +* Solutions for real time microcontroller applications * +********************************************************************** +* * +* (c) 2014 - 2016 SEGGER Microcontroller GmbH & Co. KG * +* * +* www.segger.com Support: support@segger.com * +* * +********************************************************************** +* * +* SEGGER RTT * Real Time Transfer for embedded targets * +* * +********************************************************************** +* * +* All rights reserved. * +* * +* * This software may in its unmodified form be freely redistributed * +* in source form. * +* * The source code may be modified, provided the source code * +* retains the above copyright notice, this list of conditions and * +* the following disclaimer. * +* * Modified versions of this software in source or linkable form * +* may not be distributed without prior consent of SEGGER. * +* * This software may only be used for communication with SEGGER * +* J-Link debug probes. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * +* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * +* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * +* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * +* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * +* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * +* DAMAGE. * +* * +********************************************************************** +* * +* RTT version: 5.12e * +* * +********************************************************************** +---------------------------------------------------------------------- +File : SEGGER_RTT_Conf.h +Purpose : Implementation of SEGGER real-time transfer (RTT) which + allows real-time communication on targets which support + debugger memory accesses while the CPU is running. +---------------------------END-OF-HEADER------------------------------ +*/ + +#ifndef SEGGER_RTT_CONF_H +#define SEGGER_RTT_CONF_H + +#ifdef __ICCARM__ + #include +#endif + +/********************************************************************* +* +* Defines, configurable +* +********************************************************************** +*/ + +#define SEGGER_RTT_MAX_NUM_UP_BUFFERS (2) // Max. number of up-buffers (T->H) available on this target (Default: 2) +#define SEGGER_RTT_MAX_NUM_DOWN_BUFFERS (2) // Max. number of down-buffers (H->T) available on this target (Default: 2) + +#define BUFFER_SIZE_UP (1024) // Size of the buffer for terminal output of target, up to host (Default: 1k) +#define BUFFER_SIZE_DOWN (16) // Size of the buffer for terminal input to target from host (Usually keyboard input) (Default: 16) + +#define SEGGER_RTT_PRINTF_BUFFER_SIZE (64u) // Size of buffer for RTT printf to bulk-send chars via RTT (Default: 64) + +#define SEGGER_RTT_MODE_DEFAULT SEGGER_RTT_MODE_NO_BLOCK_SKIP // Mode for pre-initialized terminal channel (buffer 0) + +// +// Target is not allowed to perform other RTT operations while string still has not been stored completely. +// Otherwise we would probably end up with a mixed string in the buffer. +// If using RTT from within interrupts, multiple tasks or multi processors, define the SEGGER_RTT_LOCK() and SEGGER_RTT_UNLOCK() function here. +// +// SEGGER_RTT_MAX_INTERRUPT_PRIORITY can be used in the sample lock routines on Cortex-M3/4. +// Make sure to mask all interrupts which can send RTT data, i.e. generate SystemView events, or cause task switches. +// When high-priority interrupts must not be masked while sending RTT data, SEGGER_RTT_MAX_INTERRUPT_PRIORITY needs to be adjusted accordingly. +// (Higher priority = lower priority number) +// Default value for embOS: 128u +// Default configuration in FreeRTOS: configMAX_SYSCALL_INTERRUPT_PRIORITY: ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) ) +// In case of doubt mask all interrupts: 0u +// + +#define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20) // Interrupt priority to lock on SEGGER_RTT_LOCK on Cortex-M3/4 (Default: 0x20) + +/********************************************************************* +* +* RTT lock configuration for SEGGER Embedded Studio, +* Rowley CrossStudio and GCC +*/ +#if (defined __SES_ARM) || (defined __CROSSWORKS_ARM) || (defined __GNUC__) + #ifdef __ARM_ARCH_6M__ + #define SEGGER_RTT_LOCK() { \ + unsigned int LockState; \ + __asm volatile ("mrs %0, primask \n\t" \ + "mov r1, $1 \n\t" \ + "msr primask, r1 \n\t" \ + : "=r" (LockState) \ + : \ + : "r1" \ + ); + + #define SEGGER_RTT_UNLOCK() __asm volatile ("msr primask, %0 \n\t" \ + : \ + : "r" (LockState) \ + : \ + ); \ + } + + #elif (defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)) + #ifndef SEGGER_RTT_MAX_INTERRUPT_PRIORITY + #define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20) + #endif + #define SEGGER_RTT_LOCK() { \ + unsigned int LockState; \ + __asm volatile ("mrs %0, basepri \n\t" \ + "mov r1, %1 \n\t" \ + "msr basepri, r1 \n\t" \ + : "=r" (LockState) \ + : "i"(SEGGER_RTT_MAX_INTERRUPT_PRIORITY) \ + : "r1" \ + ); + + #define SEGGER_RTT_UNLOCK() __asm volatile ("msr basepri, %0 \n\t" \ + : \ + : "r" (LockState) \ + : \ + ); \ + } + + #elif defined(__ARM_ARCH_7A__) + #define SEGGER_RTT_LOCK() { \ + unsigned int LockState; \ + __asm volatile ("mrs r1, CPSR \n\t" \ + "mov %0, r1 \n\t" \ + "orr r1, r1, #0xC0 \n\t" \ + "msr CPSR_c, r1 \n\t" \ + : "=r" (LockState) \ + : \ + : "r1" \ + ); + + #define SEGGER_RTT_UNLOCK() __asm volatile ("mov r0, %0 \n\t" \ + "mrs r1, CPSR \n\t" \ + "bic r1, r1, #0xC0 \n\t" \ + "and r0, r0, #0xC0 \n\t" \ + "orr r1, r1, r0 \n\t" \ + "msr CPSR_c, r1 \n\t" \ + : \ + : "r" (LockState) \ + : "r0", "r1" \ + ); \ + } +#else + #define SEGGER_RTT_LOCK() + #define SEGGER_RTT_UNLOCK() + #endif +#endif + +/********************************************************************* +* +* RTT lock configuration for IAR EWARM +*/ +#ifdef __ICCARM__ + #if (defined (__ARM6M__) && (__CORE__ == __ARM6M__)) + #define SEGGER_RTT_LOCK() { \ + unsigned int LockState; \ + LockState = __get_PRIMASK(); \ + __set_PRIMASK(1); + + #define SEGGER_RTT_UNLOCK() __set_PRIMASK(LockState); \ + } + #elif ((defined (__ARM7EM__) && (__CORE__ == __ARM7EM__)) || (defined (__ARM7M__) && (__CORE__ == __ARM7M__))) + #ifndef SEGGER_RTT_MAX_INTERRUPT_PRIORITY + #define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20) + #endif + #define SEGGER_RTT_LOCK() { \ + unsigned int LockState; \ + LockState = __get_BASEPRI(); \ + __set_BASEPRI(SEGGER_RTT_MAX_INTERRUPT_PRIORITY); + + #define SEGGER_RTT_UNLOCK() __set_BASEPRI(LockState); \ + } + #endif +#endif + +/********************************************************************* +* +* RTT lock configuration for KEIL ARM +*/ +#ifdef __CC_ARM + #if (defined __TARGET_ARCH_6S_M) + #define SEGGER_RTT_LOCK() { \ + unsigned int LockState; \ + register unsigned char PRIMASK __asm( "primask"); \ + LockState = PRIMASK; \ + PRIMASK = 1u; \ + __schedule_barrier(); + + #define SEGGER_RTT_UNLOCK() PRIMASK = LockState; \ + __schedule_barrier(); \ + } + #elif (defined(__TARGET_ARCH_7_M) || defined(__TARGET_ARCH_7E_M)) + #ifndef SEGGER_RTT_MAX_INTERRUPT_PRIORITY + #define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20) + #endif + #define SEGGER_RTT_LOCK() { \ + unsigned int LockState; \ + register unsigned char BASEPRI __asm( "basepri"); \ + LockState = BASEPRI; \ + BASEPRI = SEGGER_RTT_MAX_INTERRUPT_PRIORITY; \ + __schedule_barrier(); + + #define SEGGER_RTT_UNLOCK() BASEPRI = LockState; \ + __schedule_barrier(); \ + } + #endif +#endif + +/********************************************************************* +* +* RTT lock configuration fallback +*/ +#ifndef SEGGER_RTT_LOCK + #define SEGGER_RTT_LOCK() // Lock RTT (nestable) (i.e. disable interrupts) +#endif + +#ifndef SEGGER_RTT_UNLOCK + #define SEGGER_RTT_UNLOCK() // Unlock RTT (nestable) (i.e. enable previous interrupt lock state) +#endif + +#endif +/*************************** End of file ****************************/ diff --git a/examples/device/nrf52840_freertos/src/segger_rtt/SEGGER_RTT_SES.c b/examples/device/nrf52840_freertos/src/segger_rtt/SEGGER_RTT_SES.c new file mode 100644 index 000000000..e6634147c --- /dev/null +++ b/examples/device/nrf52840_freertos/src/segger_rtt/SEGGER_RTT_SES.c @@ -0,0 +1,76 @@ +/********************************************************************* +* SEGGER MICROCONTROLLER GmbH & Co. KG * +* Solutions for real time microcontroller applications * +********************************************************************** +* * +* (c) 2014 - 2015 SEGGER Microcontroller GmbH & Co. KG * +* * +* www.segger.com Support: support@segger.com * +* * +********************************************************************** +* * +* All rights reserved. * +* * +* * This software may in its unmodified form be freely redistributed * +* in source form. * +* * The source code may be modified, provided the source code * +* retains the above copyright notice, this list of conditions and * +* the following disclaimer. * +* * Modified versions of this software in source or linkable form * +* may not be distributed without prior consent of SEGGER. * +* * This software may only be used for communication with SEGGER * +* J-Link debug probes. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * +* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * +* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * +* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * +* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * +* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * +* DAMAGE. * +* * +********************************************************************** +-------- END-OF-HEADER --------------------------------------------- +File : SEGGER_RTT_Syscalls_SES.c +Purpose : Reimplementation of printf, puts and + implementation of __putchar and __getchar using RTT in SES. + To use RTT for printf output, include this file in your + application. +---------------------------------------------------------------------- +*/ +#include "SEGGER_RTT.h" +#include "__libc.h" +#include +#include + +int printf(const char *fmt,...) { + char buffer[128]; + va_list args; + va_start (args, fmt); + int n = vsnprintf(buffer, sizeof(buffer), fmt, args); + SEGGER_RTT_Write(0, buffer, n); + va_end(args); + return n; +} + +int puts(const char *s) { + return SEGGER_RTT_WriteString(0, s); +} + +int __putchar(int x, __printf_tag_ptr ctx) { + (void)ctx; + SEGGER_RTT_Write(0, (char *)&x, 1); + return x; +} + +int __getchar() { + return SEGGER_RTT_WaitKey(); +} + +/****** End Of File *************************************************/ diff --git a/examples/device/nrf52840_freertos/src/tusb_config.h b/examples/device/nrf52840_freertos/src/tusb_config.h index 96d851f90..9641f7bde 100644 --- a/examples/device/nrf52840_freertos/src/tusb_config.h +++ b/examples/device/nrf52840_freertos/src/tusb_config.h @@ -55,7 +55,7 @@ /*------------- RTOS -------------*/ #define CFG_TUSB_OS OPT_OS_FREERTOS -#define CFG_TUD_TASK_PRIO (configMAX_PRIORITIES-3) +#define CFG_TUD_TASK_PRIO (configMAX_PRIORITIES-1) //#define CFG_TUD_TASK_QUEUE_SZ 16 //#define CFG_TUD_TASK_STACK_SZ 150 diff --git a/hw/bsp/pca10056/board_pca10056.c b/hw/bsp/pca10056/board_pca10056.c index 928c39acf..54b1488a8 100644 --- a/hw/bsp/pca10056/board_pca10056.c +++ b/hw/bsp/pca10056/board_pca10056.c @@ -98,6 +98,11 @@ void board_init(void) nrf_gpio_cfg_output(BOARD_LED2); nrf_gpio_cfg_output(BOARD_LED3); + board_led_control(BOARD_LED0, false); + board_led_control(BOARD_LED1, false); + board_led_control(BOARD_LED2, false); + board_led_control(BOARD_LED3, false); + // Button for(uint8_t i=0; irx_ff, ser->rx_ff_buf, CFG_TUD_CDC_RX_BUFSIZE, 1, true); - tu_fifo_config_mutex(&ser->rx_ff, osal_mutex_create(&ser->rx_ff_mutex)); - tu_fifo_config(&ser->tx_ff, ser->tx_ff_buf, CFG_TUD_CDC_TX_BUFSIZE, 1, false); + +#if CFG_FIFO_MUTEX + tu_fifo_config_mutex(&ser->rx_ff, osal_mutex_create(&ser->rx_ff_mutex)); tu_fifo_config_mutex(&ser->tx_ff, osal_mutex_create(&ser->tx_ff_mutex)); +#endif } } diff --git a/src/class/cdc/cdc_device.h b/src/class/cdc/cdc_device.h index 2e03793a9..f1bd33953 100644 --- a/src/class/cdc/cdc_device.h +++ b/src/class/cdc/cdc_device.h @@ -77,6 +77,7 @@ char tud_cdc_n_peek (uint8_t itf, int pos); uint32_t tud_cdc_n_write_char (uint8_t itf, char ch); uint32_t tud_cdc_n_write (uint8_t itf, void const* buffer, uint32_t bufsize); +uint32_t tud_cdc_n_write_str (uint8_t itf, char const* str); bool tud_cdc_n_write_flush (uint8_t itf); //--------------------------------------------------------------------+ @@ -95,6 +96,7 @@ static inline char tud_cdc_peek (int pos) static inline uint32_t tud_cdc_write_char (char ch) { return tud_cdc_n_write_char(0, ch); } static inline uint32_t tud_cdc_write (void const* buffer, uint32_t bufsize) { return tud_cdc_n_write(0, buffer, bufsize); } +static inline uint32_t tud_cdc_write_str (char const* str) { return tud_cdc_n_write_str(0, str); } static inline bool tud_cdc_write_flush (void) { return tud_cdc_n_write_flush(0); } //--------------------------------------------------------------------+ diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index e0b3d0aa0..2acd4b696 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -42,25 +42,16 @@ #include "tusb_fifo.h" // implement mutex lock and unlock -// For OSAL_NONE: if mutex is locked by other, function return immediately (since there is no task context) -// For Real RTOS: fifo lock is a blocking API #if CFG_FIFO_MUTEX -static bool tu_fifo_lock(tu_fifo_t *f) +static void tu_fifo_lock(tu_fifo_t *f) { if (f->mutex) { -#if CFG_TUSB_OS == OPT_OS_NONE - // There is no subtask context for blocking mutex, we will check and return if cannot lock the mutex - if ( !osal_mutex_lock_notask(f->mutex) ) return false; -#else uint32_t err; (void) err; osal_mutex_lock(f->mutex, OSAL_TIMEOUT_WAIT_FOREVER, &err); -#endif } - - return true; } static void tu_fifo_unlock(tu_fifo_t *f) @@ -73,14 +64,14 @@ static void tu_fifo_unlock(tu_fifo_t *f) #else -#define tu_fifo_lock(_ff) true +#define tu_fifo_lock(_ff) #define tu_fifo_unlock(_ff) #endif bool tu_fifo_config(tu_fifo_t *f, void* buffer, uint16_t depth, uint16_t item_size, bool overwritable) { - if ( !tu_fifo_lock(f) ) return false; + tu_fifo_lock(f); f->buffer = (uint8_t*) buffer; f->depth = depth; @@ -115,7 +106,7 @@ bool tu_fifo_read(tu_fifo_t* f, void * p_buffer) { if( tu_fifo_empty(f) ) return false; - if ( !tu_fifo_lock(f) ) return false; + tu_fifo_lock(f); memcpy(p_buffer, f->buffer + (f->rd_idx * f->item_size), @@ -216,7 +207,7 @@ bool tu_fifo_write (tu_fifo_t* f, const void * p_data) { if ( tu_fifo_full(f) && !f->overwritable ) return false; - if ( !tu_fifo_lock(f) ) return false; + tu_fifo_lock(f); memcpy( f->buffer + (f->wr_idx * f->item_size), p_data, @@ -279,7 +270,7 @@ uint16_t tu_fifo_write_n (tu_fifo_t* f, const void * p_data, uint16_t count) /******************************************************************************/ bool tu_fifo_clear(tu_fifo_t *f) { - if ( !tu_fifo_lock(f) ) return false; + tu_fifo_lock(f); f->rd_idx = f->wr_idx = f->count = 0; diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index 70dc087c2..61d92b602 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -43,7 +43,9 @@ #ifndef _TUSB_FIFO_H_ #define _TUSB_FIFO_H_ -#define CFG_FIFO_MUTEX 1 +// mutex is only needed for RTOS +// for OS None, we don't get preempted +#define CFG_FIFO_MUTEX (CFG_TUSB_OS != OPT_OS_NONE) #include #include diff --git a/src/osal/osal_none.h b/src/osal/osal_none.h index 796ddc15f..f70c99c7f 100644 --- a/src/osal/osal_none.h +++ b/src/osal/osal_none.h @@ -178,19 +178,6 @@ static inline osal_mutex_t osal_mutex_create(osal_mutex_def_t* mdef) #define osal_mutex_unlock(_mutex_hdl) osal_semaphore_post(_mutex_hdl, false) #define osal_mutex_lock osal_semaphore_wait -// check if mutex is available for non-thread/substask usage in some cases -static inline bool osal_mutex_lock_notask(osal_mutex_t mutex_hdl) -{ - if (mutex_hdl->count) - { - mutex_hdl->count--; - return true; - }else - { - return false; - } -} - //--------------------------------------------------------------------+ // QUEUE API //--------------------------------------------------------------------+ -- cgit v1.3.1 From 215f8603b14cc29e08d8a25e08f8eca44ed90826 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 16 Nov 2018 21:56:39 +0700 Subject: nrf5x: refactor device control transfer. - make control transfer as part of usbd. Class driver must use usbd_control_ API() instead of dcd_ api. - change the signature of class driver's control_request - allow control request complete to stall in staus stage - move control request parser & handling to usbd. --- src/class/cdc/cdc_device.c | 90 +++++++------- src/class/cdc/cdc_device.h | 4 +- src/class/custom/custom_device.c | 4 +- src/class/custom/custom_device.h | 4 +- src/class/hid/hid_device.c | 141 ++++++++++----------- src/class/hid/hid_device.h | 5 +- src/class/msc/msc_device.c | 71 ++++++++--- src/class/msc/msc_device.h | 30 +---- src/common/tusb_types.h | 6 +- src/device/control.c | 261 +++++++++++++-------------------------- src/device/control.h | 38 ------ src/device/dcd.h | 4 + src/device/usbd.c | 236 ++++++++++++++++++++++++++++------- src/device/usbd_pvt.h | 17 ++- src/tusb_option.h | 4 +- 15 files changed, 477 insertions(+), 438 deletions(-) (limited to 'src/common') diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index bc16699f1..d8ade9c7f 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -45,7 +45,6 @@ // INCLUDE //--------------------------------------------------------------------+ #include "cdc_device.h" -#include "device/control.h" #include "device/usbd_pvt.h" //--------------------------------------------------------------------+ @@ -63,7 +62,7 @@ typedef struct /*------------- From this point, data is not cleared by bus reset -------------*/ char wanted_char; - CFG_TUSB_MEM_ALIGN cdc_line_coding_t line_coding; + cdc_line_coding_t line_coding; // FIFO tu_fifo_t rx_ff; @@ -199,23 +198,23 @@ void cdcd_init(void) for(uint8_t i=0; iwanted_char = -1; + p_cdc->wanted_char = -1; // default line coding is : stop bit = 1, parity = none, data bits = 8 - ser->line_coding.bit_rate = 115200; - ser->line_coding.stop_bits = 0; - ser->line_coding.parity = 0; - ser->line_coding.data_bits = 8; + p_cdc->line_coding.bit_rate = 115200; + p_cdc->line_coding.stop_bits = 0; + p_cdc->line_coding.parity = 0; + p_cdc->line_coding.data_bits = 8; // config fifo - tu_fifo_config(&ser->rx_ff, ser->rx_ff_buf, CFG_TUD_CDC_RX_BUFSIZE, 1, true); - tu_fifo_config(&ser->tx_ff, ser->tx_ff_buf, CFG_TUD_CDC_TX_BUFSIZE, 1, false); + tu_fifo_config(&p_cdc->rx_ff, p_cdc->rx_ff_buf, CFG_TUD_CDC_RX_BUFSIZE, 1, true); + tu_fifo_config(&p_cdc->tx_ff, p_cdc->tx_ff_buf, CFG_TUD_CDC_TX_BUFSIZE, 1, false); #if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&ser->rx_ff, osal_mutex_create(&ser->rx_ff_mutex)); - tu_fifo_config_mutex(&ser->tx_ff, osal_mutex_create(&ser->tx_ff_mutex)); + tu_fifo_config_mutex(&p_cdc->rx_ff, osal_mutex_create(&p_cdc->rx_ff_mutex)); + tu_fifo_config_mutex(&p_cdc->tx_ff, osal_mutex_create(&p_cdc->tx_ff_mutex)); #endif } } @@ -299,57 +298,64 @@ tusb_error_t cdcd_open(uint8_t rhport, tusb_desc_interface_t const * p_interface return TUSB_ERROR_NONE; } -void cdcd_control_request_complete(uint8_t rhport, tusb_control_request_t const * p_request) +// Invoked when class request DATA stage is finished. +// return false to stall control endpoint (e.g Host send non-sense DATA) +bool cdcd_control_request_complete(uint8_t rhport, tusb_control_request_t const * request) { //------------- Class Specific Request -------------// - if (p_request->bmRequestType_bit.type != TUSB_REQ_TYPE_CLASS) return; + TU_VERIFY (request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS); // TODO Support multiple interfaces uint8_t const itf = 0; cdcd_interface_t* p_cdc = &_cdcd_itf[itf]; // Invoke callback - if (CDC_REQUEST_SET_LINE_CODING == p_request->bRequest) { + if ( CDC_REQUEST_SET_LINE_CODING == request->bRequest ) + { if ( tud_cdc_line_coding_cb ) tud_cdc_line_coding_cb(itf, &p_cdc->line_coding); } + + return true; } -tusb_error_t cdcd_control_request(uint8_t rhport, tusb_control_request_t const * p_request, uint16_t bytes_already_sent) +// Handle class control request +// return false to stall control endpoint (e.g unsupported request) +bool cdcd_control_request(uint8_t rhport, tusb_control_request_t const * request) { //------------- Class Specific Request -------------// - if (p_request->bmRequestType_bit.type != TUSB_REQ_TYPE_CLASS) return TUSB_ERROR_DCD_CONTROL_REQUEST_NOT_SUPPORT; + TU_ASSERT(request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS); // TODO Support multiple interfaces uint8_t const itf = 0; cdcd_interface_t* p_cdc = &_cdcd_itf[itf]; - if ((CDC_REQUEST_SET_LINE_CODING == p_request->bRequest) ) - { - uint16_t len = tu_min16(sizeof(cdc_line_coding_t), p_request->wLength); - dcd_edpt_xfer(rhport, 0, (uint8_t*) &p_cdc->line_coding, len); - } - else if ( (CDC_REQUEST_GET_LINE_CODING == p_request->bRequest)) - { - uint16_t len = tu_min16(sizeof(cdc_line_coding_t), p_request->wLength); - dcd_edpt_xfer(rhport, TUSB_DIR_IN_MASK, (uint8_t*) &p_cdc->line_coding, len); - } - else if (CDC_REQUEST_SET_CONTROL_LINE_STATE == p_request->bRequest ) - { - // CDC PSTN v1.2 section 6.3.12 - // Bit 0: Indicates if DTE is present or not. - // This signal corresponds to V.24 signal 108/2 and RS-232 signal DTR (Data Terminal Ready) - // Bit 1: Carrier control for half-duplex modems. - // This signal corresponds to V.24 signal 105 and RS-232 signal RTS (Request to Send) - p_cdc->line_state = (uint8_t) p_request->wValue; - - // Invoke callback - if ( tud_cdc_line_state_cb) tud_cdc_line_state_cb(itf, BIT_TEST_(p_request->wValue, 0), BIT_TEST_(p_request->wValue, 1)); - } - else + switch ( request->bRequest ) { - return TUSB_ERROR_FAILED; // stall unsupported request + case CDC_REQUEST_SET_LINE_CODING: + usbd_control_xfer(rhport, request, &p_cdc->line_coding, sizeof(cdc_line_coding_t)); + break; + + case CDC_REQUEST_GET_LINE_CODING: + usbd_control_xfer(rhport, request, &p_cdc->line_coding, sizeof(cdc_line_coding_t)); + break; + + case CDC_REQUEST_SET_CONTROL_LINE_STATE: + // CDC PSTN v1.2 section 6.3.12 + // Bit 0: Indicates if DTE is present or not. + // This signal corresponds to V.24 signal 108/2 and RS-232 signal DTR (Data Terminal Ready) + // Bit 1: Carrier control for half-duplex modems. + // This signal corresponds to V.24 signal 105 and RS-232 signal RTS (Request to Send) + p_cdc->line_state = (uint8_t) request->wValue; + + // Invoke callback + if ( tud_cdc_line_state_cb) tud_cdc_line_state_cb(itf, BIT_TEST_(request->wValue, 0), BIT_TEST_(request->wValue, 1)); + usbd_control_status(rhport, request); + break; + + default: return false; // stall unsupported request } - return TUSB_ERROR_NONE; + + return true; } tusb_error_t cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, tusb_event_t event, uint32_t xferred_bytes) diff --git a/src/class/cdc/cdc_device.h b/src/class/cdc/cdc_device.h index 9d0b93c6d..749351a54 100644 --- a/src/class/cdc/cdc_device.h +++ b/src/class/cdc/cdc_device.h @@ -114,8 +114,8 @@ ATTR_WEAK void tud_cdc_line_coding_cb(uint8_t itf, cdc_line_coding_t const* p_li void cdcd_init (void); tusb_error_t cdcd_open (uint8_t rhport, tusb_desc_interface_t const * p_interface_desc, uint16_t *p_length); -tusb_error_t cdcd_control_request (uint8_t rhport, tusb_control_request_t const * p_request, uint16_t bytes_already_sent); -void cdcd_control_request_complete (uint8_t rhport, tusb_control_request_t const * p_request); +bool cdcd_control_request (uint8_t rhport, tusb_control_request_t const * p_request); +bool cdcd_control_request_complete (uint8_t rhport, tusb_control_request_t const * p_request); tusb_error_t cdcd_xfer_cb (uint8_t rhport, uint8_t edpt_addr, tusb_event_t event, uint32_t xferred_bytes); void cdcd_reset (uint8_t rhport); diff --git a/src/class/custom/custom_device.c b/src/class/custom/custom_device.c index 1b36f1331..cc440fc7e 100644 --- a/src/class/custom/custom_device.c +++ b/src/class/custom/custom_device.c @@ -89,9 +89,9 @@ tusb_error_t cusd_open(uint8_t rhport, tusb_desc_interface_t const * p_desc_itf, return TUSB_ERROR_NONE; } -tusb_error_t cusd_control_request(uint8_t rhport, tusb_control_request_t const * p_request) +bool cusd_control_request(uint8_t rhport, tusb_control_request_t const * p_request) { - return TUSB_ERROR_DCD_CONTROL_REQUEST_NOT_SUPPORT; + return false; } tusb_error_t cusd_xfer_cb(uint8_t rhport, uint8_t edpt_addr, tusb_event_t event, uint32_t xferred_bytes) diff --git a/src/class/custom/custom_device.h b/src/class/custom/custom_device.h index 116c6897d..704c4127b 100644 --- a/src/class/custom/custom_device.h +++ b/src/class/custom/custom_device.h @@ -64,8 +64,8 @@ void cusd_init(void); tusb_error_t cusd_open(uint8_t rhport, tusb_desc_interface_t const * p_interface_desc, uint16_t *p_length); -tusb_error_t cusd_control_request_st(uint8_t rhport, tusb_control_request_t const * p_request); -void cusd_control_request_complete (uint8_t rhport, tusb_control_request_t const * p_request); +bool cusd_control_request_st(uint8_t rhport, tusb_control_request_t const * p_request); +bool cusd_control_request_complete (uint8_t rhport, tusb_control_request_t const * p_request); tusb_error_t cusd_xfer_cb(uint8_t rhport, uint8_t edpt_addr, tusb_event_t event, uint32_t xferred_bytes); void cusd_reset(uint8_t rhport); #endif diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index efa602ad6..b5586a488 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -46,7 +46,6 @@ //--------------------------------------------------------------------+ #include "common/tusb_common.h" #include "hid_device.h" -#include "device/control.h" #include "device/usbd_pvt.h" //--------------------------------------------------------------------+ @@ -403,110 +402,112 @@ tusb_error_t hidd_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, u return TUSB_ERROR_NONE; } -tusb_error_t hidd_control_request(uint8_t rhport, tusb_control_request_t const * p_request, uint16_t bytes_already_sent) +// Handle class control request +// return false to stall control endpoint (e.g unsupported request) +bool hidd_control_request(uint8_t rhport, tusb_control_request_t const * p_request) { hidd_interface_t* p_hid = get_interface_by_itfnum( (uint8_t) p_request->wIndex ); - TU_ASSERT(p_hid, TUSB_ERROR_FAILED); + TU_ASSERT(p_hid); - //------------- STD Request -------------// if (p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD) { + //------------- STD Request -------------// uint8_t const desc_type = tu_u16_high(p_request->wValue); uint8_t const desc_index = tu_u16_low (p_request->wValue); (void) desc_index; if (p_request->bRequest == TUSB_REQ_GET_DESCRIPTOR && desc_type == HID_DESC_TYPE_REPORT) { - // TODO: Handle zero length packet. - uint16_t remaining_bytes = p_hid->desc_len - bytes_already_sent; - if (remaining_bytes > 64) { - remaining_bytes = 64; - } - memcpy(_shared_control_buffer, p_hid->desc_report + bytes_already_sent, remaining_bytes); - - dcd_edpt_xfer(rhport, TUSB_DIR_IN_MASK, _shared_control_buffer, remaining_bytes); + usbd_control_xfer(rhport, p_request, p_hid->desc_report, p_hid->desc_len); }else { - return TUSB_ERROR_FAILED; + return false; // stall unsupported request } } - //------------- Class Specific Request -------------// else if (p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS) { - if( HID_REQ_CONTROL_GET_REPORT == p_request->bRequest ) + //------------- Class Specific Request -------------// + switch( p_request->bRequest ) { - // wValue = Report Type | Report ID - uint8_t const report_type = tu_u16_high(p_request->wValue); - uint8_t const report_id = tu_u16_low(p_request->wValue); - - uint16_t xferlen; - if ( p_hid->get_report_cb ) + case HID_REQ_CONTROL_GET_REPORT: { - xferlen = p_hid->get_report_cb(report_id, (hid_report_type_t) report_type, p_hid->report_buf, p_request->wLength); - }else + // wValue = Report Type | Report ID + uint8_t const report_type = tu_u16_high(p_request->wValue); + uint8_t const report_id = tu_u16_low(p_request->wValue); + + uint16_t xferlen; + if ( p_hid->get_report_cb ) + { + xferlen = p_hid->get_report_cb(report_id, (hid_report_type_t) report_type, p_hid->report_buf, p_request->wLength); + }else + { + // For boot Interface only: re-use report_buf -> report has no change + xferlen = p_request->wLength; + } + + TU_ASSERT( xferlen > 0 ); + usbd_control_xfer(rhport, p_request, p_hid->report_buf, xferlen); + } + break; + + case HID_REQ_CONTROL_SET_REPORT: + usbd_control_xfer(rhport, p_request, p_hid->report_buf, p_request->wLength); + break; + + case HID_REQ_CONTROL_SET_IDLE: + // TODO idle rate of report + p_hid->idle_rate = tu_u16_high(p_request->wValue); + usbd_control_status(rhport, p_request); + break; + + case HID_REQ_CONTROL_GET_IDLE: + // TODO idle rate of report + usbd_control_xfer(rhport, p_request, &p_hid->idle_rate, 1); + break; + + case HID_REQ_CONTROL_GET_PROTOCOL: { - // For boot Interface only: re-use report_buf -> report has no change - xferlen = p_request->wLength; + uint8_t protocol = 1-p_hid->boot_protocol; // 0 is Boot, 1 is Report protocol + usbd_control_xfer(rhport, p_request, &protocol, 1); } + break; - TU_ASSERT( xferlen > 0 ); - dcd_edpt_xfer(rhport, TUSB_DIR_IN_MASK, _shared_control_buffer, xferlen); - } - else if ( HID_REQ_CONTROL_SET_REPORT == p_request->bRequest ) - { - dcd_edpt_xfer(rhport, 0, _shared_control_buffer, p_request->wLength); - } - else if (HID_REQ_CONTROL_SET_IDLE == p_request->bRequest) - { - // TODO idle rate of report - p_hid->idle_rate = tu_u16_high(p_request->wValue); - } - else if (HID_REQ_CONTROL_GET_IDLE == p_request->bRequest) - { - // TODO idle rate of report - _shared_control_buffer[0] = p_hid->idle_rate; - dcd_edpt_xfer(rhport, TUSB_DIR_IN_MASK, _shared_control_buffer, 1); - } - else if (HID_REQ_CONTROL_GET_PROTOCOL == p_request->bRequest ) - { - _shared_control_buffer[0] = 1-p_hid->boot_protocol; // 0 is Boot, 1 is Report protocol - dcd_edpt_xfer(rhport, TUSB_DIR_IN_MASK, _shared_control_buffer, 1); - } - else if (HID_REQ_CONTROL_SET_PROTOCOL == p_request->bRequest ) - { - p_hid->boot_protocol = 1 - p_request->wValue; // 0 is Boot, 1 is Report protocol - }else - { - return TUSB_ERROR_FAILED; + case HID_REQ_CONTROL_SET_PROTOCOL: + p_hid->boot_protocol = 1 - p_request->wValue; // 0 is Boot, 1 is Report protocol + usbd_control_status(rhport, p_request); + break; + + default: return false; // stall unsupported request } }else { - return TUSB_ERROR_FAILED; + return false; // stall unsupported request } - return TUSB_ERROR_NONE; + + return true; } -void hidd_control_request_complete(uint8_t rhport, tusb_control_request_t const * p_request) +// Invoked when class request DATA stage is finished. +// return false to stall control endpoint (e.g Host send non-sense DATA) +bool hidd_control_request_complete(uint8_t rhport, tusb_control_request_t const * p_request) { hidd_interface_t* p_hid = get_interface_by_itfnum( (uint8_t) p_request->wIndex ); - if (p_hid == NULL) { - return; - } + TU_ASSERT(p_hid); - if (p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS) + if (p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS && + p_request->bRequest == HID_REQ_CONTROL_SET_REPORT) { - if ( HID_REQ_CONTROL_SET_REPORT == p_request->bRequest ) - { - // wValue = Report Type | Report ID - uint8_t const report_type = tu_u16_high(p_request->wValue); - uint8_t const report_id = tu_u16_low(p_request->wValue); + // wValue = Report Type | Report ID + uint8_t const report_type = tu_u16_high(p_request->wValue); + uint8_t const report_id = tu_u16_low(p_request->wValue); - if ( p_hid->set_report_cb ) - { - p_hid->set_report_cb(report_id, (hid_report_type_t) report_type, _shared_control_buffer, p_request->wLength); - } + if ( p_hid->set_report_cb ) + { + p_hid->set_report_cb(report_id, (hid_report_type_t) report_type, p_hid->report_buf, p_request->wLength); } } + + return true; } tusb_error_t hidd_xfer_cb(uint8_t rhport, uint8_t edpt_addr, tusb_event_t event, uint32_t xferred_bytes) diff --git a/src/class/hid/hid_device.h b/src/class/hid/hid_device.h index 1dc40af57..7f8cd0fa7 100644 --- a/src/class/hid/hid_device.h +++ b/src/class/hid/hid_device.h @@ -378,8 +378,8 @@ ATTR_WEAK void tud_hid_mouse_set_report_cb(uint8_t report_id, hid_report_type_t void hidd_init(void); tusb_error_t hidd_open(uint8_t rhport, tusb_desc_interface_t const * p_interface_desc, uint16_t *p_length); -tusb_error_t hidd_control_request(uint8_t rhport, tusb_control_request_t const * p_request, uint16_t bytes_already_sent); -void hidd_control_request_complete (uint8_t rhport, tusb_control_request_t const * p_request); +bool hidd_control_request(uint8_t rhport, tusb_control_request_t const * p_request); +bool hidd_control_request_complete (uint8_t rhport, tusb_control_request_t const * p_request); tusb_error_t hidd_xfer_cb(uint8_t rhport, uint8_t edpt_addr, tusb_event_t event, uint32_t xferred_bytes); void hidd_reset(uint8_t rhport); @@ -390,3 +390,4 @@ void hidd_reset(uint8_t rhport); #endif #endif /* _TUSB_HID_DEVICE_H_ */ + diff --git a/src/class/msc/msc_device.c b/src/class/msc/msc_device.c index 32ad90102..92bc4c6c8 100644 --- a/src/class/msc/msc_device.c +++ b/src/class/msc/msc_device.c @@ -47,7 +47,6 @@ #include "common/tusb_common.h" #include "msc_device.h" -#include "device/control.h" #include "device/usbd_pvt.h" //--------------------------------------------------------------------+ @@ -60,7 +59,31 @@ enum MSC_STAGE_STATUS }; -CFG_TUSB_ATTR_USBRAM CFG_TUSB_MEM_ALIGN mscd_interface_t _mscd_itf; +typedef struct { + CFG_TUSB_MEM_ALIGN msc_cbw_t cbw; + +//#if defined (__ICCARM__) && (CFG_TUSB_MCU == OPT_MCU_LPC11UXX || CFG_TUSB_MCU == OPT_MCU_LPC13UXX) +// uint8_t padding1[64-sizeof(msc_cbw_t)]; // IAR cannot align struct's member +//#endif + + CFG_TUSB_MEM_ALIGN msc_csw_t csw; + + uint8_t itf_num; + uint8_t ep_in; + uint8_t ep_out; + + // Bulk Only Transfer (BOT) Protocol + uint8_t stage; + uint32_t total_len; + uint32_t xferred_len; // numbered of bytes transferred so far in the Data Stage + + // Sense Response Data + uint8_t sense_key; + uint8_t add_sense_code; + uint8_t add_sense_qualifier; +}mscd_interface_t; + +CFG_TUSB_ATTR_USBRAM CFG_TUSB_MEM_ALIGN static mscd_interface_t _mscd_itf; CFG_TUSB_ATTR_USBRAM CFG_TUSB_MEM_ALIGN static uint8_t _mscd_buf[CFG_TUD_MSC_BUFSIZE]; //--------------------------------------------------------------------+ @@ -147,29 +170,39 @@ tusb_error_t mscd_open(uint8_t rhport, tusb_desc_interface_t const * p_desc_itf, return TUSB_ERROR_NONE; } -tusb_error_t mscd_control_request(uint8_t rhport, tusb_control_request_t const * p_request, uint16_t bytes_already_sent) +// Handle class control request +// return false to stall control endpoint (e.g unsupported request) +bool mscd_control_request(uint8_t rhport, tusb_control_request_t const * p_request) { - TU_ASSERT(p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS, TUSB_ERROR_DCD_CONTROL_REQUEST_NOT_SUPPORT); + TU_ASSERT(p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS); - if(MSC_REQ_RESET == p_request->bRequest) - { - // TODO: Actually reset. - } - else if (MSC_REQ_GET_MAX_LUN == p_request->bRequest) + switch ( p_request->bRequest ) { - // returned MAX LUN is minus 1 by specs - _shared_control_buffer[0] = CFG_TUD_MSC_MAXLUN-1; - dcd_edpt_xfer(rhport, TUSB_DIR_IN_MASK, _shared_control_buffer, 1); - }else - { - return TUSB_ERROR_FAILED; // stall unsupported request + case MSC_REQ_RESET: + // TODO: Actually reset interface. + usbd_control_status(rhport, p_request); + break; + + case MSC_REQ_GET_MAX_LUN: + { + // returned MAX LUN is minus 1 by specs + uint8_t maxlun = CFG_TUD_MSC_MAXLUN-1; + usbd_control_xfer(rhport, p_request, &maxlun, 1); + } + break; + + default: return false; // stall unsupported request } - return TUSB_ERROR_NONE; + + return true; } -void mscd_control_request_complete(uint8_t rhport, tusb_control_request_t const * p_request) +// Invoked when class request DATA stage is finished. +// return false to stall control endpoint (e.g Host send non-sense DATA) +bool mscd_control_request_complete(uint8_t rhport, tusb_control_request_t const * p_request) { - return; + // nothing to do + return true; } // For backwards compatibility we support static block counts. @@ -296,7 +329,7 @@ int32_t proc_builtin_scsi(msc_cbw_t const * p_cbw, uint8_t* buffer, uint32_t buf return ret; } -tusb_error_t mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, uint8_t event, uint32_t xferred_bytes) +tusb_error_t mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, tusb_event_t event, uint32_t xferred_bytes) { mscd_interface_t* p_msc = &_mscd_itf; msc_cbw_t const * p_cbw = &p_msc->cbw; diff --git a/src/class/msc/msc_device.h b/src/class/msc/msc_device.h index ac3eade22..d08d9f9cb 100644 --- a/src/class/msc/msc_device.h +++ b/src/class/msc/msc_device.h @@ -81,32 +81,6 @@ TU_VERIFY_STATIC(CFG_TUD_MSC_BUFSIZE < UINT16_MAX, "Size is not correct"); extern "C" { #endif -typedef struct { - CFG_TUSB_MEM_ALIGN msc_cbw_t cbw; - -//#if defined (__ICCARM__) && (CFG_TUSB_MCU == OPT_MCU_LPC11UXX || CFG_TUSB_MCU == OPT_MCU_LPC13UXX) -// uint8_t padding1[64-sizeof(msc_cbw_t)]; // IAR cannot align struct's member -//#endif - - CFG_TUSB_MEM_ALIGN msc_csw_t csw; - - uint8_t itf_num; - uint8_t ep_in; - uint8_t ep_out; - - // Bulk Only Transfer (BOT) Protocol - uint8_t stage; - uint32_t total_len; - uint32_t xferred_len; // numbered of bytes transferred so far in the Data Stage - - // Sense Response Data - uint8_t sense_key; - uint8_t add_sense_code; - uint8_t add_sense_qualifier; -}mscd_interface_t; - -extern mscd_interface_t _mscd_itf; - /** \addtogroup ClassDriver_MSC * @{ * \defgroup MSC_Device Device @@ -198,8 +172,8 @@ ATTR_WEAK bool tud_lun_capacity_cb(uint8_t lun, uint32_t* last_valid_sector, uin void mscd_init(void); tusb_error_t mscd_open(uint8_t rhport, tusb_desc_interface_t const * p_interface_desc, uint16_t *p_length); -tusb_error_t mscd_control_request(uint8_t rhport, tusb_control_request_t const * p_request, uint16_t bytes_already_sent); -void mscd_control_request_complete (uint8_t rhport, tusb_control_request_t const * p_request); +bool mscd_control_request(uint8_t rhport, tusb_control_request_t const * p_request); +bool mscd_control_request_complete (uint8_t rhport, tusb_control_request_t const * p_request); tusb_error_t mscd_xfer_cb(uint8_t rhport, uint8_t edpt_addr, tusb_event_t event, uint32_t xferred_bytes); void mscd_reset(uint8_t rhport); diff --git a/src/common/tusb_types.h b/src/common/tusb_types.h index 5c226f556..32632cd90 100644 --- a/src/common/tusb_types.h +++ b/src/common/tusb_types.h @@ -203,12 +203,14 @@ typedef enum TUSB_EVENT_XFER_STALLED, }tusb_event_t; -enum { +enum +{ DESC_OFFSET_LEN = 0, DESC_OFFSET_TYPE = 1 }; -enum { +enum +{ INTERFACE_INVALID_NUMBER = 0xff }; diff --git a/src/device/control.c b/src/device/control.c index 35ae536e1..7ab1e16ab 100644 --- a/src/device/control.c +++ b/src/device/control.c @@ -46,216 +46,125 @@ #include "control.h" #include "device/usbd_pvt.h" +enum +{ + EDPT_CTRL_OUT = 0x00, + EDPT_CTRL_IN = 0x80 +}; + +typedef struct { + tusb_control_request_t request; + + void* buffer; + uint16_t total_len; + uint16_t total_transferred; + + bool (*complete_cb) (uint8_t, tusb_control_request_t const * ); +} control_t; + control_t control_state; -CFG_TUSB_ATTR_USBRAM CFG_TUSB_MEM_ALIGN uint8_t _shared_control_buffer[64]; +CFG_TUSB_ATTR_USBRAM CFG_TUSB_MEM_ALIGN uint8_t _usbd_ctrl_buf[CFG_TUD_ENDOINT0_SIZE]; -void controld_reset(uint8_t rhport) { - control_state.current_stage = CONTROL_STAGE_SETUP; +void usbd_control_reset (uint8_t rhport) +{ + tu_varclr(&control_state); } -// Helper to send STATUS (zero length) packet -// Note dir is value of direction bit in setup packet (i.e DATA stage direction) -static inline bool dcd_control_status(uint8_t rhport, uint8_t dir) +void usbd_control_stall(uint8_t rhport) { - uint8_t ep_addr = 0; - // Invert the direction. - if (dir == TUSB_DIR_OUT) { - ep_addr |= TUSB_DIR_IN_MASK; - } - // status direction is reversed to one in the setup packet - return dcd_edpt_xfer(rhport, ep_addr, NULL, 0); + dcd_edpt_stall(rhport, 0); } -static inline void dcd_control_stall(uint8_t rhport) +bool usbd_control_status(uint8_t rhport, tusb_control_request_t const * request) { - dcd_edpt_stall(rhport, 0 | TUSB_DIR_IN_MASK); + // status direction is reversed to one in the setup packet + return dcd_edpt_xfer(rhport, request->bmRequestType_bit.direction ? EDPT_CTRL_OUT : EDPT_CTRL_IN, NULL, 0); } -// return len of descriptor and change pointer to descriptor's buffer -static uint16_t get_descriptor(uint8_t rhport, tusb_control_request_t const * const p_request, uint8_t const ** pp_buffer) +// Each transaction is up to endpoint0's max packet size +static bool start_control_data_xact(uint8_t rhport) { - (void) rhport; - - tusb_desc_type_t const desc_type = (tusb_desc_type_t) tu_u16_high(p_request->wValue); - uint8_t const desc_index = tu_u16_low( p_request->wValue ); + uint16_t const xact_len = tu_min16(control_state.total_len - control_state.total_transferred, CFG_TUD_ENDOINT0_SIZE); - uint8_t const * desc_data = NULL ; - uint16_t len = 0; + uint8_t ep_addr = EDPT_CTRL_OUT; - switch(desc_type) + if ( control_state.request.bmRequestType_bit.direction == TUSB_DIR_IN ) { - case TUSB_DESC_DEVICE: - desc_data = (uint8_t const *) usbd_desc_set->device; - len = sizeof(tusb_desc_device_t); - break; - - case TUSB_DESC_CONFIGURATION: - desc_data = (uint8_t const *) usbd_desc_set->config; - len = ((tusb_desc_configuration_t const*) desc_data)->wTotalLength; - break; - - case TUSB_DESC_STRING: - // String Descriptor always uses the desc set from user - if ( desc_index < tud_desc_set.string_count ) - { - desc_data = tud_desc_set.string_arr[desc_index]; - TU_VERIFY( desc_data != NULL, 0 ); - - len = desc_data[0]; // first byte of descriptor is its size - }else - { - // out of range - /* The 0xee string is indeed a Microsoft USB extension. - * It can be used to tell Windows what driver it should use for the device !!! - */ - return 0; - } - break; - - case TUSB_DESC_DEVICE_QUALIFIER: - // TODO If not highspeed capable stall this request otherwise - // return the descriptor that could work in highspeed - return 0; - break; - - default: return 0; + ep_addr = EDPT_CTRL_IN; + memcpy(_usbd_ctrl_buf, control_state.buffer, xact_len); } - TU_ASSERT( desc_data != NULL, 0); - - // up to Host's length - len = tu_min16(p_request->wLength, len ); - (*pp_buffer) = desc_data; - - return len; + return dcd_edpt_xfer(rhport, ep_addr, _usbd_ctrl_buf, xact_len); } -tusb_error_t controld_xfer_cb(uint8_t rhport, uint8_t edpt_addr, tusb_event_t event, uint32_t xferred_bytes) { - if (control_state.current_stage == CONTROL_STAGE_STATUS && xferred_bytes == 0) { - control_state.current_stage = CONTROL_STAGE_SETUP; - return TUSB_ERROR_NONE; - } - tusb_error_t error = TUSB_ERROR_NONE; - control_state.total_transferred += xferred_bytes; - tusb_control_request_t const *p_request = &control_state.current_request; - - if (p_request->wLength == control_state.total_transferred || xferred_bytes < 64) { - control_state.current_stage = CONTROL_STAGE_STATUS; - dcd_control_status(rhport, p_request->bmRequestType_bit.direction); - - // Do the user callback after queueing the STATUS packet because the callback could be slow. - if ( TUSB_REQ_RCPT_INTERFACE == p_request->bmRequestType_bit.recipient ) - { - tud_control_interface_control_complete_cb(rhport, tu_u16_low(p_request->wIndex), p_request); - } - } else { - if (TUSB_REQ_RCPT_INTERFACE == p_request->bmRequestType_bit.recipient) { - error = tud_control_interface_control_cb(rhport, tu_u16_low(p_request->wIndex), p_request, control_state.total_transferred); - } else { - error = controld_process_control_request(rhport, p_request, control_state.total_transferred); - } - } - return error; +// TODO may find a better way +void usbd_control_set_complete_callback( bool (*fp) (uint8_t, tusb_control_request_t const * ) ) +{ + control_state.complete_cb = fp; } -// This tracks the state of a control request. -tusb_error_t controld_process_setup_request(uint8_t rhport, tusb_control_request_t const * p_request) { - tusb_error_t error = TUSB_ERROR_NONE; - memcpy(&control_state.current_request, p_request, sizeof(tusb_control_request_t)); - if (p_request->wLength == 0) { - control_state.current_stage = CONTROL_STAGE_STATUS; - } else { - control_state.current_stage = CONTROL_STAGE_DATA; - control_state.total_transferred = 0; - } +bool usbd_control_xfer(uint8_t rhport, tusb_control_request_t const * request, void* buffer, uint16_t len) +{ + control_state.request = (*request); + control_state.buffer = buffer; + control_state.total_len = tu_min16(len, request->wLength); + control_state.total_transferred = 0; - if ( TUSB_REQ_RCPT_INTERFACE == p_request->bmRequestType_bit.recipient ) + if ( buffer != NULL && len ) { - error = tud_control_interface_control_cb(rhport, tu_u16_low(p_request->wIndex), p_request, 0); - } else { - error = controld_process_control_request(rhport, p_request, 0); + // Data stage + TU_ASSERT( start_control_data_xact(rhport) ); + }else + { + // Status stage + TU_ASSERT( usbd_control_status(rhport, request) ); } - if (error != TUSB_ERROR_NONE) { - dcd_control_stall(rhport); // Stall errored requests - } else if (control_state.current_stage == CONTROL_STAGE_STATUS) { - dcd_control_status(rhport, p_request->bmRequestType_bit.direction); - } - return error; + return true; } -// This handles the actual request and its response. -tusb_error_t controld_process_control_request(uint8_t rhport, tusb_control_request_t const * p_request, uint16_t bytes_already_sent) +// callback when a transaction complete on DATA stage of control endpoint +tusb_error_t usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, tusb_event_t event, uint32_t xferred_bytes) { - tusb_error_t error = TUSB_ERROR_NONE; - uint8_t ep_addr = 0; - if (p_request->bmRequestType_bit.direction == TUSB_DIR_IN) { - ep_addr |= TUSB_DIR_IN_MASK; + if ( control_state.request.bmRequestType_bit.direction == TUSB_DIR_OUT ) + { + memcpy(control_state.buffer, _usbd_ctrl_buf, xferred_bytes); } - //------------- Standard Request e.g in enumeration -------------// - if( TUSB_REQ_RCPT_DEVICE == p_request->bmRequestType_bit.recipient && - TUSB_REQ_TYPE_STANDARD == p_request->bmRequestType_bit.type ) { - switch (p_request->bRequest) { - case TUSB_REQ_GET_DESCRIPTOR: { - uint8_t const * buffer = NULL; - uint16_t const len = get_descriptor(rhport, p_request, &buffer); - - if (len) { - uint16_t remaining_bytes = len - bytes_already_sent; - if (remaining_bytes > 64) { - remaining_bytes = 64; - } - memcpy(_shared_control_buffer, buffer + bytes_already_sent, remaining_bytes); - dcd_edpt_xfer(rhport, ep_addr, _shared_control_buffer, remaining_bytes); - } else { - return TUSB_ERROR_FAILED; - } - break; - } - case TUSB_REQ_GET_CONFIGURATION: - memcpy(_shared_control_buffer, &control_state.config, 1); - dcd_edpt_xfer(rhport, ep_addr, _shared_control_buffer, 1); - break; - case TUSB_REQ_SET_ADDRESS: - dcd_set_address(rhport, (uint8_t) p_request->wValue); - break; - case TUSB_REQ_SET_CONFIGURATION: - control_state.config = p_request->wValue; - tud_control_set_config_cb (rhport, control_state.config); - break; - default: - return TUSB_ERROR_FAILED; + control_state.total_transferred += xferred_bytes; + control_state.buffer += xferred_bytes; + + if ( control_state.total_len == control_state.total_transferred || xferred_bytes < CFG_TUD_ENDOINT0_SIZE ) + { + // DATA stage is complete + bool is_ok = true; + + // invoke complete callback if set + // callback can still stall control in status phase e.g out data does not make sense + if ( control_state.complete_cb ) + { + is_ok = control_state.complete_cb(rhport, &control_state.request); } - } else if (p_request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_ENDPOINT && - p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD) { - //------------- Endpoint Request -------------// - switch (p_request->bRequest) { - case TUSB_REQ_GET_STATUS: { - uint16_t status = dcd_edpt_stalled(rhport, tu_u16_low(p_request->wIndex)) ? 0x0001 : 0x0000; - memcpy(_shared_control_buffer, &status, 2); - - dcd_edpt_xfer(rhport, ep_addr, _shared_control_buffer, 2); - break; - } - case TUSB_REQ_CLEAR_FEATURE: - // only endpoint feature is halted/stalled - dcd_edpt_clear_stall(rhport, tu_u16_low(p_request->wIndex)); - break; - case TUSB_REQ_SET_FEATURE: - // only endpoint feature is halted/stalled - dcd_edpt_stall(rhport, tu_u16_low(p_request->wIndex)); - break; - default: - return TUSB_ERROR_FAILED; + + if ( is_ok ) + { + // Send status + TU_ASSERT( usbd_control_status(rhport, &control_state.request), TUSB_ERROR_FAILED ); + }else + { + // stall due to callback + usbd_control_stall(rhport); } - } else { - //------------- Unsupported Request -------------// - return TUSB_ERROR_FAILED; } - return error; + else + { + // More data to transfer + TU_ASSERT(start_control_data_xact(rhport), TUSB_ERROR_FAILED); + } + + return TUSB_ERROR_NONE; } #endif diff --git a/src/device/control.h b/src/device/control.h index e8dcf76f9..e1709bcee 100644 --- a/src/device/control.h +++ b/src/device/control.h @@ -48,44 +48,6 @@ #include "tusb.h" -typedef enum { - CONTROL_STAGE_SETUP, // Waiting for a setup token. - CONTROL_STAGE_DATA, // In the process of sending or receiving data. - CONTROL_STAGE_STATUS // In the process of transmitting the STATUS ZLP. -} control_stage_t; - -typedef struct { - control_stage_t current_stage; - tusb_control_request_t current_request; - uint16_t total_transferred; - uint8_t config; -} control_t; - -extern uint8_t _shared_control_buffer[64]; - -tusb_error_t controld_process_setup_request(uint8_t rhport, tusb_control_request_t const * const p_request); - -// Callback when the configuration of the device is changed. -tusb_error_t tud_control_set_config_cb(uint8_t rhport, uint8_t config_number); - -// Called when the DATA stage of a control transaction is complete. -void tud_control_interface_control_complete_cb(uint8_t rhport, uint8_t interface, tusb_control_request_t const * const p_request); - -tusb_error_t tud_control_interface_control_cb(uint8_t rhport, uint8_t interface, tusb_control_request_t const * const p_request, uint16_t bytes_already_sent); - -//--------------------------------------------------------------------+ -// INTERNAL API -//--------------------------------------------------------------------+ -tusb_error_t controld_open(uint8_t rhport, tusb_desc_interface_t const * p_interface_desc, uint16_t *p_length); - -// This tracks the state of a control request. -tusb_error_t controld_process_setup_request(uint8_t rhport, tusb_control_request_t const * p_request); - -// This handles the actual request and its response. -tusb_error_t controld_process_control_request(uint8_t rhport, tusb_control_request_t const * p_request, uint16_t bytes_already_sent); - -tusb_error_t controld_xfer_cb(uint8_t rhport, uint8_t edpt_addr, tusb_event_t event, uint32_t xferred_bytes); -void controld_reset(uint8_t rhport); #ifdef __cplusplus } diff --git a/src/device/dcd.h b/src/device/dcd.h index ff836f405..bd0ea852e 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -124,6 +124,10 @@ void dcd_event_xfer_complete (uint8_t rhport, uint8_t ep_addr, uint32_t xferred_ /*------------------------------------------------------------------*/ /* Endpoint API + * Note: + * - Address of control endpoint OUT is 0x00, In is 0x80 + * - When stalling control endpoint both control OUT and IN must be stalled + * (according to USB spec, stalled control is only recovered with setup token) *------------------------------------------------------------------*/ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc); bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes); diff --git a/src/device/usbd.c b/src/device/usbd.c index 13cc7f332..e9ac24c4b 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -68,11 +68,10 @@ typedef struct { uint8_t config_num; - // map interface number to driver (0xff is invalid) - uint8_t itf2drv[16]; + uint8_t itf2drv[16]; // map interface number to driver (0xff is invalid) + uint8_t ep2drv[2][8]; // map endpoint to driver ( 0xff is invalid ) + - // map endpoint to driver ( 0xff is invalid ) - uint8_t ep2drv[2][8]; }usbd_device_t; static usbd_device_t _usbd_dev; @@ -94,9 +93,8 @@ typedef struct { void (* init ) (void); tusb_error_t (* open ) (uint8_t rhport, tusb_desc_interface_t const * desc_intf, uint16_t* p_length); - // Control request is called one or more times for a request and can queue multiple data packets. - tusb_error_t (* control_request ) (uint8_t rhport, tusb_control_request_t const *, uint16_t bytes_already_sent); - void (* control_request_complete ) (uint8_t rhport, tusb_control_request_t const *); + bool (* control_request ) (uint8_t rhport, tusb_control_request_t const * request); + bool (* control_request_complete ) (uint8_t rhport, tusb_control_request_t const * request); tusb_error_t (* xfer_cb ) (uint8_t rhport, uint8_t ep_addr, tusb_event_t, uint32_t); void (* sof ) (uint8_t rhport); void (* reset ) (uint8_t); @@ -171,9 +169,16 @@ OSAL_QUEUE_DEF(_usbd_qdef, CFG_TUD_TASK_QUEUE_SZ, dcd_event_t); static osal_queue_t _usbd_q; //--------------------------------------------------------------------+ -// INTERNAL FUNCTION +// Prototypes //--------------------------------------------------------------------+ static void mark_interface_endpoint(uint8_t const* p_desc, uint16_t desc_len, uint8_t driver_id); +static bool process_control_request(uint8_t rhport, tusb_control_request_t const * p_request); +static bool process_set_config(uint8_t rhport, uint8_t config_number); +static void const* get_descriptor(tusb_control_request_t const * p_request, uint16_t* desc_len); + +void usbd_control_reset (uint8_t rhport); +tusb_error_t usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, tusb_event_t event, uint32_t xferred_bytes); +void usbd_control_set_complete_callback( bool (*fp) (uint8_t, tusb_control_request_t const * ) ); //--------------------------------------------------------------------+ // APPLICATION API @@ -184,7 +189,7 @@ bool tud_mounted(void) } //--------------------------------------------------------------------+ -// IMPLEMENTATION +// USBD Task //--------------------------------------------------------------------+ tusb_error_t usbd_init (void) { @@ -214,7 +219,7 @@ static void usbd_reset(uint8_t rhport) memset(_usbd_dev.itf2drv, 0xff, sizeof(_usbd_dev.itf2drv)); // invalid mapping memset(_usbd_dev.ep2drv , 0xff, sizeof(_usbd_dev.ep2drv )); // invalid mapping - controld_reset(rhport); + usbd_control_reset(rhport); for (uint8_t i = 0; i < USBD_CLASS_DRIVER_COUNT; i++) { @@ -222,20 +227,24 @@ static void usbd_reset(uint8_t rhport) } } +// Main device task implementation static void usbd_task_body(void) { - dcd_event_t event; - // Loop until there is no more events in the queue while (1) { + dcd_event_t event; + if ( !osal_queue_receive(_usbd_q, &event) ) return; switch ( event.event_id ) { case DCD_EVENT_SETUP_RECEIVED: - // Setup tokens are unique to the Control endpoint so we delegate to it directly. - controld_process_setup_request(event.rhport, &event.setup_received); + // Process control request, if failed control endpoint is stalled + if ( !process_control_request(event.rhport, &event.setup_received) ) + { + usbd_control_stall(event.rhport); + } break; case DCD_EVENT_XFER_COMPLETE: @@ -245,8 +254,8 @@ static void usbd_task_body(void) if ( 0 == edpt_number(ep_addr) ) { - // control transfer - controld_xfer_cb(event.rhport, ep_addr, event.xfer_complete.result, event.xfer_complete.len); + // control transfer DATA stage callback + usbd_control_xfer_cb(event.rhport, ep_addr, event.xfer_complete.result, event.xfer_complete.len); } else { @@ -312,66 +321,142 @@ void usbd_task( void* param) #endif } -void tud_control_interface_control_complete_cb(uint8_t rhport, uint8_t interface, tusb_control_request_t const * const p_request) { - if (_usbd_dev.itf2drv[ interface ] < USBD_CLASS_DRIVER_COUNT) +//--------------------------------------------------------------------+ +// Control Request Parser & Handling +//--------------------------------------------------------------------+ + +// This handles the actual request and its response. +// return false will cause its caller to stall control endpoint +static bool process_control_request(uint8_t rhport, tusb_control_request_t const * p_request) +{ + usbd_control_set_complete_callback(NULL); + + if ( TUSB_REQ_RCPT_DEVICE == p_request->bmRequestType_bit.recipient && + TUSB_REQ_TYPE_STANDARD == p_request->bmRequestType_bit.type ) + { + //------------- Standard Device Requests e.g in enumeration -------------// + void* data_buf = NULL; + uint16_t data_len = 0; + + switch ( p_request->bRequest ) { - const usbd_class_driver_t *driver = &usbd_class_drivers[_usbd_dev.itf2drv[interface]]; - if (driver->control_request_complete != NULL) { - driver->control_request_complete(rhport, p_request); + case TUSB_REQ_SET_ADDRESS: + dcd_set_address(rhport, (uint8_t) p_request->wValue); + break; + + case TUSB_REQ_GET_CONFIGURATION: + data_buf = &_usbd_dev.config_num; + data_len = 1; + break; + + case TUSB_REQ_SET_CONFIGURATION: + { + uint8_t const config = (uint8_t) p_request->wValue; + + dcd_set_config(rhport, config); + _usbd_dev.config_num = config; + + TU_ASSERT( TUSB_ERROR_NONE == process_set_config(rhport, config) ); } + break; + + case TUSB_REQ_GET_DESCRIPTOR: + data_buf = (void*) get_descriptor(p_request, &data_len); + if ( data_buf == NULL || data_len == 0 ) return false; + break; + + default: return false; } -} -tusb_error_t tud_control_interface_control_cb(uint8_t rhport, uint8_t interface, tusb_control_request_t const * const p_request, uint16_t bytes_already_sent) { - if (_usbd_dev.itf2drv[ interface ] < USBD_CLASS_DRIVER_COUNT) + usbd_control_xfer(rhport, p_request, data_buf, data_len); + } + else if ( TUSB_REQ_RCPT_INTERFACE == p_request->bmRequestType_bit.recipient ) + { + //------------- Class/Interface Specific Request -------------// + uint8_t const itf = tu_u16_low(p_request->wIndex); + uint8_t const drvid = _usbd_dev.itf2drv[ itf ]; + + TU_VERIFY (drvid < USBD_CLASS_DRIVER_COUNT ); + + usbd_control_set_complete_callback(usbd_class_drivers[drvid].control_request_complete ); + + // control endpoint will be stalled if driver return false + return usbd_class_drivers[drvid].control_request(rhport, p_request); + } + else if ( p_request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_ENDPOINT && + p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD ) + { + //------------- Endpoint Request -------------// + switch ( p_request->bRequest ) { - return usbd_class_drivers[_usbd_dev.itf2drv[interface]].control_request(rhport, p_request, bytes_already_sent); + case TUSB_REQ_GET_STATUS: + { + uint16_t status = dcd_edpt_stalled(rhport, tu_u16_low(p_request->wIndex)) ? 0x0001 : 0x0000; + usbd_control_xfer(rhport, p_request, &status, 2); + } + break; + + case TUSB_REQ_CLEAR_FEATURE: + // only endpoint feature is halted/stalled + dcd_edpt_clear_stall(rhport, tu_u16_low(p_request->wIndex)); + usbd_control_status(rhport, p_request); + break; + + case TUSB_REQ_SET_FEATURE: + // only endpoint feature is halted/stalled + dcd_edpt_stall(rhport, tu_u16_low(p_request->wIndex)); + usbd_control_status(rhport, p_request); + break; + + default: return false; } - return TUSB_ERROR_FAILED; + } + else + { + //------------- Unsupported Request -------------// + return false; + } + + return true; } // Process Set Configure Request -// TODO Host (windows) can get HID report descriptor before set configured -// may need to open interface before set configured -tusb_error_t tud_control_set_config_cb(uint8_t rhport, uint8_t config_number) +// This function parse configuration descriptor & open drivers accordingly +static bool process_set_config(uint8_t rhport, uint8_t config_number) { - dcd_set_config(rhport, config_number); - - _usbd_dev.config_num = config_number; - - //------------- parse configuration & open drivers -------------// uint8_t const * desc_cfg = (uint8_t const *) usbd_desc_set->config; - TU_ASSERT(desc_cfg != NULL, TUSB_ERROR_DESCRIPTOR_CORRUPTED); + TU_ASSERT(desc_cfg != NULL); + uint8_t const * p_desc = desc_cfg + sizeof(tusb_desc_configuration_t); uint16_t const cfg_len = ((tusb_desc_configuration_t*)desc_cfg)->wTotalLength; while( p_desc < desc_cfg + cfg_len ) { + // Each interface always starts with Interface or Association descriptor if ( TUSB_DESC_INTERFACE_ASSOCIATION == descriptor_type(p_desc) ) { p_desc = descriptor_next(p_desc); // ignore Interface Association }else { - TU_ASSERT( TUSB_DESC_INTERFACE == descriptor_type(p_desc), TUSB_ERROR_NOT_SUPPORTED_YET ); + TU_ASSERT( TUSB_DESC_INTERFACE == descriptor_type(p_desc) ); - tusb_desc_interface_t* p_desc_itf = (tusb_desc_interface_t*) p_desc; - uint8_t const class_code = p_desc_itf->bInterfaceClass; + tusb_desc_interface_t* desc_itf = (tusb_desc_interface_t*) p_desc; // Check if class is supported uint8_t drv_id; for (drv_id = 0; drv_id < USBD_CLASS_DRIVER_COUNT; drv_id++) { - if ( usbd_class_drivers[drv_id].class_code == class_code ) break; + if ( usbd_class_drivers[drv_id].class_code == desc_itf->bInterfaceClass ) break; } - TU_ASSERT( drv_id < USBD_CLASS_DRIVER_COUNT, TUSB_ERROR_NOT_SUPPORTED_YET ); + TU_ASSERT( drv_id < USBD_CLASS_DRIVER_COUNT ); // unsupported class - // Interface number must not be used - TU_ASSERT( 0xff == _usbd_dev.itf2drv[p_desc_itf->bInterfaceNumber], TUSB_ERROR_FAILED); - _usbd_dev.itf2drv[p_desc_itf->bInterfaceNumber] = drv_id; + // Interface number must not be used already TODO alternate interface + TU_ASSERT( 0xff == _usbd_dev.itf2drv[desc_itf->bInterfaceNumber] ); + _usbd_dev.itf2drv[desc_itf->bInterfaceNumber] = drv_id; uint16_t len=0; - TU_ASSERT_ERR( usbd_class_drivers[drv_id].open( rhport, p_desc_itf, &len ) ); - TU_ASSERT( len >= sizeof(tusb_desc_interface_t), TUSB_ERROR_FAILED ); + TU_ASSERT_ERR( usbd_class_drivers[drv_id].open( rhport, desc_itf, &len ), false ); + TU_ASSERT( len >= sizeof(tusb_desc_interface_t) ); mark_interface_endpoint(p_desc, len, drv_id); @@ -404,8 +489,62 @@ static void mark_interface_endpoint(uint8_t const* p_desc, uint16_t desc_len, ui } } +// return descriptor's buffer and update desc_len +static void const* get_descriptor(tusb_control_request_t const * p_request, uint16_t* desc_len) +{ + tusb_desc_type_t const desc_type = (tusb_desc_type_t) tu_u16_high(p_request->wValue); + uint8_t const desc_index = tu_u16_low( p_request->wValue ); + + uint8_t const * desc_data = NULL; + uint16_t len = 0; + + *desc_len = 0; + + switch(desc_type) + { + case TUSB_DESC_DEVICE: + desc_data = (uint8_t const *) usbd_desc_set->device; + len = sizeof(tusb_desc_device_t); + break; + + case TUSB_DESC_CONFIGURATION: + desc_data = (uint8_t const *) usbd_desc_set->config; + len = ((tusb_desc_configuration_t const*) desc_data)->wTotalLength; + break; + + case TUSB_DESC_STRING: + // String Descriptor always uses the desc set from user + if ( desc_index < tud_desc_set.string_count ) + { + desc_data = tud_desc_set.string_arr[desc_index]; + TU_VERIFY( desc_data != NULL, NULL ); + + len = desc_data[0]; // first byte of descriptor is its size + }else + { + // out of range + /* The 0xEE index string is a Microsoft USB extension. + * It can be used to tell Windows what driver it should use for the device !!! + */ + return NULL; + } + break; + + case TUSB_DESC_DEVICE_QUALIFIER: + // TODO If not highspeed capable stall this request otherwise + // return the descriptor that could work in highspeed + return NULL; + break; + + default: return NULL; + } + + *desc_len = len; + return desc_data; +} + //--------------------------------------------------------------------+ -// USBD-DCD Callback API +// DCD Event Handler //--------------------------------------------------------------------+ void dcd_event_handler(dcd_event_t const * event, bool in_isr) { @@ -430,6 +569,9 @@ void dcd_event_handler(dcd_event_t const * event, bool in_isr) break; case DCD_EVENT_XFER_COMPLETE: + // skip zero-length control status complete event, should dcd notifies us. + if ( 0 == edpt_number(event->xfer_complete.ep_addr) && event->xfer_complete.len == 0) break; + osal_queue_send(_usbd_q, event, in_isr); TU_ASSERT(event->xfer_complete.result == DCD_XFER_SUCCESS,); break; @@ -438,8 +580,6 @@ void dcd_event_handler(dcd_event_t const * event, bool in_isr) } } -void dcd_event_handler(dcd_event_t const * event, bool in_isr); - // helper to send bus signal event void dcd_event_bus_signal (uint8_t rhport, dcd_eventid_t eid, bool in_isr) { diff --git a/src/device/usbd_pvt.h b/src/device/usbd_pvt.h index bbbe0a604..30f010887 100644 --- a/src/device/usbd_pvt.h +++ b/src/device/usbd_pvt.h @@ -54,15 +54,24 @@ extern tud_desc_set_t const* usbd_desc_set; tusb_error_t usbd_init (void); void usbd_task (void* param); + +// Carry out Data and Status stage of control transfer +// - If len = 0, it is equivalent to sending status only +// - If len > wLength : it will be truncated +bool usbd_control_xfer(uint8_t rhport, tusb_control_request_t const * request, void* buffer, uint16_t len); + +// Send STATUS (zero length) packet +bool usbd_control_status(uint8_t rhport, tusb_control_request_t const * request); + +// Stall control endpoint until new setup packet arrived +void usbd_control_stall(uint8_t rhport); + /*------------------------------------------------------------------*/ -/* Endpoint helper +/* Helper *------------------------------------------------------------------*/ // helper to parse an pair of In and Out endpoint descriptors. They must be consecutive tusb_error_t usbd_open_edpt_pair(uint8_t rhport, tusb_desc_endpoint_t const* p_desc_ep, uint8_t xfer_type, uint8_t* ep_out, uint8_t* ep_in); -/*------------------------------------------------------------------*/ -/* Other Helpers - *------------------------------------------------------------------*/ void usbd_defer_func( osal_task_func_t func, void* param, bool in_isr ); diff --git a/src/tusb_option.h b/src/tusb_option.h index d027ea0e6..f19ff4076 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -148,10 +148,8 @@ #define CFG_TUD_ENDOINT0_SIZE 64 #endif - #ifndef CFG_TUD_ENUM_BUFFER_SIZE + #ifndef CFG_TUD_CTRL_BUFSIZE #define CFG_TUD_CTRL_BUFSIZE 256 - #else - #define CFG_TUD_CTRL_BUFSIZE CFG_TUD_ENUM_BUFFER_SIZE #endif #ifndef CFG_TUD_DESC_AUTO -- cgit v1.3.1 From 569e85a0c0a80848e3076b64363ce0e589d3a604 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 22 Nov 2018 17:40:20 +0700 Subject: cdc work ok with lpc43xx --- .../cdc_msc_hid/ses/lpc43xx/lpc43xx.emProject | 2 +- examples/device/cdc_msc_hid/src/tusb_config.h | 18 ++++-- src/common/compiler/tusb_compiler_gcc.h | 2 - src/common/compiler/tusb_compiler_iar.h | 2 - src/portable/nxp/lpc43xx_lpc18xx/dcd_lpc43xx.c | 71 +++++++++++----------- 5 files changed, 51 insertions(+), 44 deletions(-) (limited to 'src/common') diff --git a/examples/device/cdc_msc_hid/ses/lpc43xx/lpc43xx.emProject b/examples/device/cdc_msc_hid/ses/lpc43xx/lpc43xx.emProject index 3b91cf865..363fae3e2 100644 --- a/examples/device/cdc_msc_hid/ses/lpc43xx/lpc43xx.emProject +++ b/examples/device/cdc_msc_hid/ses/lpc43xx/lpc43xx.emProject @@ -19,7 +19,7 @@ arm_target_device_name="LPC4357_M4" arm_target_interface_type="SWD" build_treat_warnings_as_errors="Yes" - c_preprocessor_definitions="CORE_M4;__LPC4300_FAMILY;__LPC435x_SUBFAMILY;ARM_MATH_CM4;FLASH_PLACEMENT=1;BOARD_EA4357;CFG_TUSB_MCU=OPT_MCU_LPC43XX" + c_preprocessor_definitions="CORE_M4;__LPC4300_FAMILY;__LPC435x_SUBFAMILY;ARM_MATH_CM4;FLASH_PLACEMENT=1;BOARD_EA4357;CFG_TUSB_MCU=OPT_MCU_LPC43XX;CFG_TUSB_MEM_SECTION= __attribute__((section(".bss2")))" c_user_include_directories="../../src;$(rootDir)/hw/cmsis/Include;$(rootDir)/hw;$(rootDir)/src;$(lpcDir)/CMSIS_LPC43xx_DriverLib/inc" debug_register_definition_file="LPC43xx_Registers.xml" debug_target_connection="J-Link" diff --git a/examples/device/cdc_msc_hid/src/tusb_config.h b/examples/device/cdc_msc_hid/src/tusb_config.h index 3af109188..9bc97ecff 100644 --- a/examples/device/cdc_msc_hid/src/tusb_config.h +++ b/examples/device/cdc_msc_hid/src/tusb_config.h @@ -58,16 +58,24 @@ #define CFG_TUSB_DEBUG 2 #define CFG_TUSB_OS OPT_OS_NONE -//-------------------------------------------------------------------- -// USB RAM PLACEMENT -//-------------------------------------------------------------------- -#define CFG_TUSB_ATTR_USBRAM +/* USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment. + * Tinyusb use follows macros to declare transferring memory so that they can be put + * into those specific section. + * e.g + * - CFG_TUSB_MEM SECTION : __attribute__ (( section(".usb_ram") )) + * - CFG_TUSB_MEM_ALIGN : __attribute__ ((aligned(4))) + */ +#ifndef CFG_TUSB_MEM_SECTION +#define CFG_TUSB_MEM_SECTION +#endif + +#ifndef CFG_TUSB_MEM_ALIGN #define CFG_TUSB_MEM_ALIGN ATTR_ALIGNED(4) +#endif //-------------------------------------------------------------------- // DEVICE CONFIGURATION //-------------------------------------------------------------------- - #define CFG_TUD_ENDOINT0_SIZE 64 /*------------- Descriptors -------------*/ diff --git a/src/common/compiler/tusb_compiler_gcc.h b/src/common/compiler/tusb_compiler_gcc.h index c9f716d48..e40ad9c41 100644 --- a/src/common/compiler/tusb_compiler_gcc.h +++ b/src/common/compiler/tusb_compiler_gcc.h @@ -66,10 +66,8 @@ /// The packed attribute specifies that a variable or structure field should have the smallest possible alignment—one byte for a variable, and one bit for a field, unless you specify a larger value with the aligned attribute #define ATTR_PACKED __attribute__ ((packed)) - #define ATTR_PREPACKED -#define ATTR_PACKED_STRUCT(x) x __attribute__ ((packed)) /** @} */ /** \defgroup Group_FuncAttr Function Attributes diff --git a/src/common/compiler/tusb_compiler_iar.h b/src/common/compiler/tusb_compiler_iar.h index 1703ea45f..1f8936859 100644 --- a/src/common/compiler/tusb_compiler_iar.h +++ b/src/common/compiler/tusb_compiler_iar.h @@ -53,8 +53,6 @@ #endif #define ALIGN_OF(x) __ALIGNOF__(x) - -#define ATTR_PACKED_STRUCT(x) __packed x #define ATTR_PREPACKED __packed #define ATTR_PACKED //#define ATTR_SECTION(section) _Pragma((#section)) diff --git a/src/portable/nxp/lpc43xx_lpc18xx/dcd_lpc43xx.c b/src/portable/nxp/lpc43xx_lpc18xx/dcd_lpc43xx.c index 64a2c257a..07f6eef82 100644 --- a/src/portable/nxp/lpc43xx_lpc18xx/dcd_lpc43xx.c +++ b/src/portable/nxp/lpc43xx_lpc18xx/dcd_lpc43xx.c @@ -237,40 +237,7 @@ static inline uint8_t qtd_find_free(uint8_t rhport) } //--------------------------------------------------------------------+ -// CONTROL PIPE API -//--------------------------------------------------------------------+ - -// control transfer does not need to use qtd find function -// follows UM 24.10.8.1.1 Setup packet handling using setup lockout mechanism -bool dcd_control_xfer(uint8_t rhport, uint8_t dir, uint8_t * p_buffer, uint16_t length) -{ - LPC_USB0_Type* const lpc_usb = LPC_USB[rhport]; - dcd_data_t* const p_dcd = dcd_data_ptr[rhport]; - - uint8_t const ep_phy = (dir == TUSB_DIR_IN) ? 1 : 0; - - dcd_qhd_t* qhd = &p_dcd->qhd[ep_phy]; - - // wait until ENDPTSETUPSTAT before priming data/status in response TODO add time out - while(lpc_usb->ENDPTSETUPSTAT & BIT_(0)) {} - - TU_VERIFY( !qhd->qtd_overlay.active ); - - dcd_qtd_t* qtd = &p_dcd->qtd[0]; - qtd_init(qtd, p_buffer, length); - - // skip xfer complete for Status - qtd->int_on_complete = (length > 0 ? 1 : 0); - - qhd->qtd_overlay.next = (uint32_t) qtd; - - lpc_usb->ENDPTPRIME = BIT_(edpt_phy2pos(ep_phy)); - - return true; -} - -//--------------------------------------------------------------------+ -// BULK/INTERRUPT/ISOCHRONOUS PIPE API +// DCD Endpoint Port //--------------------------------------------------------------------+ static inline volatile uint32_t * get_reg_control_addr(uint8_t rhport, uint8_t physical_endpoint) { @@ -345,6 +312,36 @@ bool dcd_edpt_busy(uint8_t rhport, uint8_t ep_addr) // return !p_qhd->qtd_overlay.halted && p_qhd->qtd_overlay.active; } +// control transfer does not need to use qtd find function +// follows UM 24.10.8.1.1 Setup packet handling using setup lockout mechanism +bool dcd_control_xfer(uint8_t rhport, uint8_t dir, uint8_t * p_buffer, uint16_t length) +{ + LPC_USB0_Type* const lpc_usb = LPC_USB[rhport]; + dcd_data_t* const p_dcd = dcd_data_ptr[rhport]; + + uint8_t const ep_phy = (dir == TUSB_DIR_IN) ? 1 : 0; + + dcd_qhd_t* qhd = &p_dcd->qhd[ep_phy]; + + // wait until ENDPTSETUPSTAT before priming data/status in response TODO add time out + while(lpc_usb->ENDPTSETUPSTAT & BIT_(0)) {} + + TU_VERIFY( !qhd->qtd_overlay.active ); + + dcd_qtd_t* qtd = &p_dcd->qtd[0]; + qtd_init(qtd, p_buffer, length); + + // skip xfer complete for Status + qtd->int_on_complete = (length > 0 ? 1 : 0); + + qhd->qtd_overlay.next = (uint32_t) qtd; + + lpc_usb->ENDPTPRIME = BIT_(edpt_phy2pos(ep_phy)); + + return true; +} + + // add only, controller virtually cannot know // TODO remove and merge to dcd_edpt_xfer static bool pipe_add_xfer(uint8_t rhport, uint8_t ed_idx, void * buffer, uint16_t total_bytes, bool int_on_complete) @@ -377,6 +374,11 @@ static bool pipe_add_xfer(uint8_t rhport, uint8_t ed_idx, void * buffer, uint16_ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) { + if ( edpt_number(ep_addr) == 0 ) + { + return dcd_control_xfer(rhport, edpt_dir(ep_addr), buffer, total_bytes); + } + uint8_t ep_idx = edpt_addr2phy(ep_addr); TU_VERIFY ( pipe_add_xfer(rhport, ep_idx, buffer, total_bytes, true) ); @@ -391,6 +393,7 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t return true; } + //--------------------------------------------------------------------+ // ISR //--------------------------------------------------------------------+ -- cgit v1.3.1 From cb8782e5f28b4897e73520c91296d1ac7d71da81 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 23 Nov 2018 15:14:47 +0700 Subject: rename tusb_event_t to xfer_result_t --- examples/obsolete/device/src/keyboard_device_app.c | 2 +- examples/obsolete/device/src/mouse_device_app.c | 2 +- examples/obsolete/host/src/cdc_serial_host_app.c | 2 +- examples/obsolete/host/src/keyboard_host_app.c | 2 +- examples/obsolete/host/src/mouse_host_app.c | 2 +- examples/obsolete/host/src/msc_host_app.c | 2 +- src/class/cdc/cdc_device.c | 2 +- src/class/cdc/cdc_device.h | 2 +- src/class/cdc/cdc_host.c | 2 +- src/class/cdc/cdc_host.h | 6 +++--- src/class/cdc/cdc_rndis_host.c | 2 +- src/class/cdc/cdc_rndis_host.h | 2 +- src/class/custom/custom_device.c | 2 +- src/class/custom/custom_device.h | 2 +- src/class/custom/custom_host.c | 2 +- src/class/custom/custom_host.h | 2 +- src/class/hid/hid_device.c | 2 +- src/class/hid/hid_device.h | 2 +- src/class/hid/hid_host.c | 2 +- src/class/hid/hid_host.h | 12 ++++++------ src/class/msc/msc_device.c | 4 ++-- src/class/msc/msc_device.h | 2 +- src/class/msc/msc_host.c | 2 +- src/class/msc/msc_host.h | 6 +++--- src/common/tusb_types.h | 3 +-- src/device/usbd.c | 4 ++-- src/device/usbd_control.c | 2 +- src/host/ehci/ehci.c | 2 +- src/host/hub.c | 2 +- src/host/hub.h | 2 +- src/host/ohci/ohci.c | 2 +- src/host/usbh.c | 2 +- src/host/usbh.h | 2 +- src/host/usbh_hcd.h | 2 +- tests/lpc18xx_43xx/test/host/cdc/cdc_callback.h | 2 +- tests/lpc18xx_43xx/test/host/hid/hidh_callback.h | 4 ++-- tests/lpc18xx_43xx/test/host/msc/msch_callback.h | 2 +- 37 files changed, 49 insertions(+), 50 deletions(-) (limited to 'src/common') diff --git a/examples/obsolete/device/src/keyboard_device_app.c b/examples/obsolete/device/src/keyboard_device_app.c index f6ef77c10..6c413464e 100644 --- a/examples/obsolete/device/src/keyboard_device_app.c +++ b/examples/obsolete/device/src/keyboard_device_app.c @@ -66,7 +66,7 @@ void keyboard_app_umount(uint8_t rhport) } -void tud_hid_keyboard_cb(uint8_t rhport, tusb_event_t event, uint32_t xferred_bytes) +void tud_hid_keyboard_cb(uint8_t rhport, xfer_result_t event, uint32_t xferred_bytes) { switch(event) { diff --git a/examples/obsolete/device/src/mouse_device_app.c b/examples/obsolete/device/src/mouse_device_app.c index db685daf6..4c4d322d7 100644 --- a/examples/obsolete/device/src/mouse_device_app.c +++ b/examples/obsolete/device/src/mouse_device_app.c @@ -66,7 +66,7 @@ void mouse_app_umount(uint8_t rhport) } -void tud_hid_mouse_cb(uint8_t rhport, tusb_event_t event, uint32_t xferred_bytes) +void tud_hid_mouse_cb(uint8_t rhport, xfer_result_t event, uint32_t xferred_bytes) { switch(event) { diff --git a/examples/obsolete/host/src/cdc_serial_host_app.c b/examples/obsolete/host/src/cdc_serial_host_app.c index d16a9b411..afb2b8937 100644 --- a/examples/obsolete/host/src/cdc_serial_host_app.c +++ b/examples/obsolete/host/src/cdc_serial_host_app.c @@ -75,7 +75,7 @@ void tuh_cdc_unmounted_cb(uint8_t dev_addr) } // invoked ISR context -void tuh_cdc_xfer_isr(uint8_t dev_addr, tusb_event_t event, cdc_pipeid_t pipe_id, uint32_t xferred_bytes) +void tuh_cdc_xfer_isr(uint8_t dev_addr, xfer_result_t event, cdc_pipeid_t pipe_id, uint32_t xferred_bytes) { (void) dev_addr; // compiler warnings diff --git a/examples/obsolete/host/src/keyboard_host_app.c b/examples/obsolete/host/src/keyboard_host_app.c index 6d10e96e1..27d10b9e7 100644 --- a/examples/obsolete/host/src/keyboard_host_app.c +++ b/examples/obsolete/host/src/keyboard_host_app.c @@ -77,7 +77,7 @@ void tuh_hid_keyboard_unmounted_cb(uint8_t dev_addr) } // invoked ISR context -void tuh_hid_keyboard_isr(uint8_t dev_addr, tusb_event_t event) +void tuh_hid_keyboard_isr(uint8_t dev_addr, xfer_result_t event) { switch(event) { diff --git a/examples/obsolete/host/src/mouse_host_app.c b/examples/obsolete/host/src/mouse_host_app.c index 563b911c2..05135693b 100644 --- a/examples/obsolete/host/src/mouse_host_app.c +++ b/examples/obsolete/host/src/mouse_host_app.c @@ -76,7 +76,7 @@ void tuh_hid_mouse_unmounted_cb(uint8_t dev_addr) } // invoked ISR context -void tuh_hid_mouse_isr(uint8_t dev_addr, tusb_event_t event) +void tuh_hid_mouse_isr(uint8_t dev_addr, xfer_result_t event) { switch(event) { diff --git a/examples/obsolete/host/src/msc_host_app.c b/examples/obsolete/host/src/msc_host_app.c index 3648cb94b..1cfe9ec60 100644 --- a/examples/obsolete/host/src/msc_host_app.c +++ b/examples/obsolete/host/src/msc_host_app.c @@ -129,7 +129,7 @@ void tuh_msc_unmounted_cb(uint8_t dev_addr) } // invoked ISR context -void tuh_msc_isr(uint8_t dev_addr, tusb_event_t event, uint32_t xferred_bytes) +void tuh_msc_isr(uint8_t dev_addr, xfer_result_t event, uint32_t xferred_bytes) { (void) dev_addr; (void) event; diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index a0abd42f6..b68a6a7ff 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -358,7 +358,7 @@ bool cdcd_control_request(uint8_t rhport, tusb_control_request_t const * request return true; } -tusb_error_t cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, tusb_event_t event, uint32_t xferred_bytes) +tusb_error_t cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) { // TODO Support multiple interfaces uint8_t const itf = 0; diff --git a/src/class/cdc/cdc_device.h b/src/class/cdc/cdc_device.h index 749351a54..ad1100e9c 100644 --- a/src/class/cdc/cdc_device.h +++ b/src/class/cdc/cdc_device.h @@ -116,7 +116,7 @@ void cdcd_init (void); tusb_error_t cdcd_open (uint8_t rhport, tusb_desc_interface_t const * p_interface_desc, uint16_t *p_length); bool cdcd_control_request (uint8_t rhport, tusb_control_request_t const * p_request); bool cdcd_control_request_complete (uint8_t rhport, tusb_control_request_t const * p_request); -tusb_error_t cdcd_xfer_cb (uint8_t rhport, uint8_t edpt_addr, tusb_event_t event, uint32_t xferred_bytes); +tusb_error_t cdcd_xfer_cb (uint8_t rhport, uint8_t edpt_addr, xfer_result_t event, uint32_t xferred_bytes); void cdcd_reset (uint8_t rhport); #endif diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index af2e2c444..0a3661878 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -221,7 +221,7 @@ tusb_error_t cdch_open_subtask(uint8_t dev_addr, tusb_desc_interface_t const *p_ OSAL_SUBTASK_END } -void cdch_isr(pipe_handle_t pipe_hdl, tusb_event_t event, uint32_t xferred_bytes) +void cdch_isr(pipe_handle_t pipe_hdl, xfer_result_t event, uint32_t xferred_bytes) { tuh_cdc_xfer_isr( pipe_hdl.dev_addr, event, get_app_pipeid(pipe_hdl), xferred_bytes ); } diff --git a/src/class/cdc/cdc_host.h b/src/class/cdc/cdc_host.h index b3e995470..8cfe6e5b7 100644 --- a/src/class/cdc/cdc_host.h +++ b/src/class/cdc/cdc_host.h @@ -118,7 +118,7 @@ void tuh_cdc_unmounted_cb(uint8_t dev_addr); /** \brief Callback function that is invoked when an transferring event occurred * \param[in] dev_addr Address of device - * \param[in] event an value from \ref tusb_event_t + * \param[in] event an value from \ref xfer_result_t * \param[in] pipe_id value from \ref cdc_pipeid_t indicate the pipe * \param[in] xferred_bytes Number of bytes transferred via USB bus * \note event can be one of following @@ -127,7 +127,7 @@ void tuh_cdc_unmounted_cb(uint8_t dev_addr); * - TUSB_EVENT_XFER_STALLED : previously scheduled transfer is stalled by device. * \note */ -void tuh_cdc_xfer_isr(uint8_t dev_addr, tusb_event_t event, cdc_pipeid_t pipe_id, uint32_t xferred_bytes); +void tuh_cdc_xfer_isr(uint8_t dev_addr, xfer_result_t event, cdc_pipeid_t pipe_id, uint32_t xferred_bytes); /// @} // group CDC_Serial_Host /// @} @@ -151,7 +151,7 @@ extern cdch_data_t cdch_data[CFG_TUSB_HOST_DEVICE_MAX]; // TODO consider to move void cdch_init(void); tusb_error_t cdch_open_subtask(uint8_t dev_addr, tusb_desc_interface_t const *p_interface_desc, uint16_t *p_length) ATTR_WARN_UNUSED_RESULT; -void cdch_isr(pipe_handle_t pipe_hdl, tusb_event_t event, uint32_t xferred_bytes); +void cdch_isr(pipe_handle_t pipe_hdl, xfer_result_t event, uint32_t xferred_bytes); void cdch_close(uint8_t dev_addr); #endif diff --git a/src/class/cdc/cdc_rndis_host.c b/src/class/cdc/cdc_rndis_host.c index 42722fd0d..89ea3b32f 100644 --- a/src/class/cdc/cdc_rndis_host.c +++ b/src/class/cdc/cdc_rndis_host.c @@ -224,7 +224,7 @@ tusb_error_t rndish_open_subtask(uint8_t dev_addr, cdch_data_t *p_cdc) OSAL_SUBTASK_END } -void rndish_xfer_isr(cdch_data_t *p_cdc, pipe_handle_t pipe_hdl, tusb_event_t event, uint32_t xferred_bytes) +void rndish_xfer_isr(cdch_data_t *p_cdc, pipe_handle_t pipe_hdl, xfer_result_t event, uint32_t xferred_bytes) { if ( pipehandle_is_equal(pipe_hdl, p_cdc->pipe_notification) ) { diff --git a/src/class/cdc/cdc_rndis_host.h b/src/class/cdc/cdc_rndis_host.h index c4597daa8..3b92d3f23 100644 --- a/src/class/cdc/cdc_rndis_host.h +++ b/src/class/cdc/cdc_rndis_host.h @@ -65,7 +65,7 @@ typedef struct { void rndish_init(void); tusb_error_t rndish_open_subtask(uint8_t dev_addr, cdch_data_t *p_cdc) ATTR_WARN_UNUSED_RESULT; -void rndish_xfer_isr(cdch_data_t *p_cdc, pipe_handle_t pipe_hdl, tusb_event_t event, uint32_t xferred_bytes); +void rndish_xfer_isr(cdch_data_t *p_cdc, pipe_handle_t pipe_hdl, xfer_result_t event, uint32_t xferred_bytes); void rndish_close(uint8_t dev_addr); #endif diff --git a/src/class/custom/custom_device.c b/src/class/custom/custom_device.c index cc440fc7e..194963c17 100644 --- a/src/class/custom/custom_device.c +++ b/src/class/custom/custom_device.c @@ -94,7 +94,7 @@ bool cusd_control_request(uint8_t rhport, tusb_control_request_t const * p_reque return false; } -tusb_error_t cusd_xfer_cb(uint8_t rhport, uint8_t edpt_addr, tusb_event_t event, uint32_t xferred_bytes) +tusb_error_t cusd_xfer_cb(uint8_t rhport, uint8_t edpt_addr, xfer_result_t event, uint32_t xferred_bytes) { return TUSB_ERROR_NONE; } diff --git a/src/class/custom/custom_device.h b/src/class/custom/custom_device.h index 704c4127b..0a8f05e7d 100644 --- a/src/class/custom/custom_device.h +++ b/src/class/custom/custom_device.h @@ -66,7 +66,7 @@ void cusd_init(void); tusb_error_t cusd_open(uint8_t rhport, tusb_desc_interface_t const * p_interface_desc, uint16_t *p_length); bool cusd_control_request_st(uint8_t rhport, tusb_control_request_t const * p_request); bool cusd_control_request_complete (uint8_t rhport, tusb_control_request_t const * p_request); -tusb_error_t cusd_xfer_cb(uint8_t rhport, uint8_t edpt_addr, tusb_event_t event, uint32_t xferred_bytes); +tusb_error_t cusd_xfer_cb(uint8_t rhport, uint8_t edpt_addr, xfer_result_t event, uint32_t xferred_bytes); void cusd_reset(uint8_t rhport); #endif diff --git a/src/class/custom/custom_host.c b/src/class/custom/custom_host.c index 329012fda..9f0b70afb 100644 --- a/src/class/custom/custom_host.c +++ b/src/class/custom/custom_host.c @@ -131,7 +131,7 @@ tusb_error_t cush_open_subtask(uint8_t dev_addr, tusb_desc_interface_t const *p_ return TUSB_ERROR_NONE; } -void cush_isr(pipe_handle_t pipe_hdl, tusb_event_t event) +void cush_isr(pipe_handle_t pipe_hdl, xfer_result_t event) { } diff --git a/src/class/custom/custom_host.h b/src/class/custom/custom_host.h index 2bf3a8d3c..5f9c25dda 100644 --- a/src/class/custom/custom_host.h +++ b/src/class/custom/custom_host.h @@ -73,7 +73,7 @@ tusb_error_t tusbh_custom_write(uint8_t dev_addr, uint16_t vendor_id, uint16_t p void cush_init(void); tusb_error_t cush_open_subtask(uint8_t dev_addr, tusb_desc_interface_t const *p_interface_desc, uint16_t *p_length) ATTR_WARN_UNUSED_RESULT; -void cush_isr(pipe_handle_t pipe_hdl, tusb_event_t event); +void cush_isr(pipe_handle_t pipe_hdl, xfer_result_t event); void cush_close(uint8_t dev_addr); #endif diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index cece06ea0..f1ecec3c7 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -510,7 +510,7 @@ bool hidd_control_request_complete(uint8_t rhport, tusb_control_request_t const return true; } -tusb_error_t hidd_xfer_cb(uint8_t rhport, uint8_t edpt_addr, tusb_event_t event, uint32_t xferred_bytes) +tusb_error_t hidd_xfer_cb(uint8_t rhport, uint8_t edpt_addr, xfer_result_t event, uint32_t xferred_bytes) { // nothing to do return TUSB_ERROR_NONE; diff --git a/src/class/hid/hid_device.h b/src/class/hid/hid_device.h index 357c71082..7aff7f34d 100644 --- a/src/class/hid/hid_device.h +++ b/src/class/hid/hid_device.h @@ -380,7 +380,7 @@ void hidd_init(void); tusb_error_t hidd_open(uint8_t rhport, tusb_desc_interface_t const * p_interface_desc, uint16_t *p_length); bool hidd_control_request(uint8_t rhport, tusb_control_request_t const * p_request); bool hidd_control_request_complete (uint8_t rhport, tusb_control_request_t const * p_request); -tusb_error_t hidd_xfer_cb(uint8_t rhport, uint8_t edpt_addr, tusb_event_t event, uint32_t xferred_bytes); +tusb_error_t hidd_xfer_cb(uint8_t rhport, uint8_t edpt_addr, xfer_result_t event, uint32_t xferred_bytes); void hidd_reset(uint8_t rhport); #endif diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 7129562c5..6aa0748df 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -251,7 +251,7 @@ tusb_error_t hidh_open_subtask(uint8_t dev_addr, tusb_desc_interface_t const *p_ OSAL_SUBTASK_END } -void hidh_isr(pipe_handle_t pipe_hdl, tusb_event_t event, uint32_t xferred_bytes) +void hidh_isr(pipe_handle_t pipe_hdl, xfer_result_t event, uint32_t xferred_bytes) { (void) xferred_bytes; // TODO may need to use this para later diff --git a/src/class/hid/hid_host.h b/src/class/hid/hid_host.h index 3acc05bf7..fb10a614f 100644 --- a/src/class/hid/hid_host.h +++ b/src/class/hid/hid_host.h @@ -93,14 +93,14 @@ tusb_error_t tuh_hid_keyboard_get_report(uint8_t dev_addr, void * p_report) /*A //------------- Application Callback -------------// /** \brief Callback function that is invoked when an transferring event occurred * \param[in] dev_addr Address of device - * \param[in] event an value from \ref tusb_event_t + * \param[in] event an value from \ref xfer_result_t * \note event can be one of following * - TUSB_EVENT_XFER_COMPLETE : previously scheduled transfer completes successfully. * - TUSB_EVENT_XFER_ERROR : previously scheduled transfer encountered a transaction error. * - TUSB_EVENT_XFER_STALLED : previously scheduled transfer is stalled by device. * \note Application should schedule the next report by calling \ref tuh_hid_keyboard_get_report within this callback */ -void tuh_hid_keyboard_isr(uint8_t dev_addr, tusb_event_t event); +void tuh_hid_keyboard_isr(uint8_t dev_addr, xfer_result_t event); /** \brief Callback function that will be invoked when a device with Keyboard interface is mounted * \param[in] dev_addr Address of newly mounted device @@ -158,14 +158,14 @@ tusb_error_t tuh_hid_mouse_get_report(uint8_t dev_addr, void* p_report) /*ATTR_ //------------- Application Callback -------------// /** \brief Callback function that is invoked when an transferring event occurred * \param[in] dev_addr Address of device - * \param[in] event an value from \ref tusb_event_t + * \param[in] event an value from \ref xfer_result_t * \note event can be one of following * - TUSB_EVENT_XFER_COMPLETE : previously scheduled transfer completes successfully. * - TUSB_EVENT_XFER_ERROR : previously scheduled transfer encountered a transaction error. * - TUSB_EVENT_XFER_STALLED : previously scheduled transfer is stalled by device. * \note Application should schedule the next report by calling \ref tuh_hid_mouse_get_report within this callback */ -void tuh_hid_mouse_isr(uint8_t dev_addr, tusb_event_t event); +void tuh_hid_mouse_isr(uint8_t dev_addr, xfer_result_t event); /** \brief Callback function that will be invoked when a device with Mouse interface is mounted * \param[in] dev_addr Address of newly mounted device @@ -199,7 +199,7 @@ tusb_interface_status_t tuh_hid_generic_get_status(uint8_t dev_addr) ATTR_WARN_U tusb_interface_status_t tuh_hid_generic_set_status(uint8_t dev_addr) ATTR_WARN_UNUSED_RESULT; //------------- Application Callback -------------// -void tuh_hid_generic_isr(uint8_t dev_addr, tusb_event_t event); +void tuh_hid_generic_isr(uint8_t dev_addr, xfer_result_t event); /** @} */ // Generic_Host /** @} */ // ClassDriver_HID_Generic @@ -217,7 +217,7 @@ typedef struct { void hidh_init(void); tusb_error_t hidh_open_subtask(uint8_t dev_addr, tusb_desc_interface_t const *p_interface_desc, uint16_t *p_length) ATTR_WARN_UNUSED_RESULT; -void hidh_isr(pipe_handle_t pipe_hdl, tusb_event_t event, uint32_t xferred_bytes); +void hidh_isr(pipe_handle_t pipe_hdl, xfer_result_t event, uint32_t xferred_bytes); void hidh_close(uint8_t dev_addr); #endif diff --git a/src/class/msc/msc_device.c b/src/class/msc/msc_device.c index 78e6d0a6b..1f4252f22 100644 --- a/src/class/msc/msc_device.c +++ b/src/class/msc/msc_device.c @@ -324,7 +324,7 @@ int32_t proc_builtin_scsi(msc_cbw_t const * p_cbw, uint8_t* buffer, uint32_t buf return ret; } -tusb_error_t mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, tusb_event_t event, uint32_t xferred_bytes) +tusb_error_t mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) { mscd_interface_t* p_msc = &_mscd_itf; msc_cbw_t const * p_cbw = &p_msc->cbw; @@ -337,7 +337,7 @@ tusb_error_t mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, tusb_event_t event, u // Complete IN while waiting for CMD is usually Status of previous SCSI op, ignore it if(ep_addr != p_msc->ep_out) return TUSB_ERROR_NONE; - TU_ASSERT( event == DCD_XFER_SUCCESS && + TU_ASSERT( ((uint8_t) event) == DCD_XFER_SUCCESS && xferred_bytes == sizeof(msc_cbw_t) && p_cbw->signature == MSC_CBW_SIGNATURE, TUSB_ERROR_INVALID_PARA ); p_csw->signature = MSC_CSW_SIGNATURE; diff --git a/src/class/msc/msc_device.h b/src/class/msc/msc_device.h index c1c51255a..c4476f56f 100644 --- a/src/class/msc/msc_device.h +++ b/src/class/msc/msc_device.h @@ -180,7 +180,7 @@ void mscd_init(void); tusb_error_t mscd_open(uint8_t rhport, tusb_desc_interface_t const * p_interface_desc, uint16_t *p_length); bool mscd_control_request(uint8_t rhport, tusb_control_request_t const * p_request); bool mscd_control_request_complete (uint8_t rhport, tusb_control_request_t const * p_request); -tusb_error_t mscd_xfer_cb(uint8_t rhport, uint8_t edpt_addr, tusb_event_t event, uint32_t xferred_bytes); +tusb_error_t mscd_xfer_cb(uint8_t rhport, uint8_t edpt_addr, xfer_result_t event, uint32_t xferred_bytes); void mscd_reset(uint8_t rhport); #endif diff --git a/src/class/msc/msc_host.c b/src/class/msc/msc_host.c index bd3e92de1..baef7ff44 100644 --- a/src/class/msc/msc_host.c +++ b/src/class/msc/msc_host.c @@ -397,7 +397,7 @@ tusb_error_t msch_open_subtask(uint8_t dev_addr, tusb_desc_interface_t const *p_ OSAL_SUBTASK_END } -void msch_isr(pipe_handle_t pipe_hdl, tusb_event_t event, uint32_t xferred_bytes) +void msch_isr(pipe_handle_t pipe_hdl, xfer_result_t event, uint32_t xferred_bytes) { if ( pipehandle_is_equal(pipe_hdl, msch_data[pipe_hdl.dev_addr-1].bulk_in) ) { diff --git a/src/class/msc/msc_host.h b/src/class/msc/msc_host.h index 6d95cfe34..0afe5c515 100644 --- a/src/class/msc/msc_host.h +++ b/src/class/msc/msc_host.h @@ -171,7 +171,7 @@ void tuh_msc_unmounted_cb(uint8_t dev_addr); /** \brief Callback function that is invoked when an transferring event occurred * \param[in] dev_addr Address of device - * \param[in] event an value from \ref tusb_event_t + * \param[in] event an value from \ref xfer_result_t * \param[in] xferred_bytes Number of bytes transferred via USB bus * \note event can be one of following * - TUSB_EVENT_XFER_COMPLETE : previously scheduled transfer completes successfully. @@ -179,7 +179,7 @@ void tuh_msc_unmounted_cb(uint8_t dev_addr); * - TUSB_EVENT_XFER_STALLED : previously scheduled transfer is stalled by device. * \note */ -void tuh_msc_isr(uint8_t dev_addr, tusb_event_t event, uint32_t xferred_bytes); +void tuh_msc_isr(uint8_t dev_addr, xfer_result_t event, uint32_t xferred_bytes); //--------------------------------------------------------------------+ @@ -205,7 +205,7 @@ typedef struct { void msch_init(void); tusb_error_t msch_open_subtask(uint8_t dev_addr, tusb_desc_interface_t const *p_interface_desc, uint16_t *p_length) ATTR_WARN_UNUSED_RESULT; -void msch_isr(pipe_handle_t pipe_hdl, tusb_event_t event, uint32_t xferred_bytes); +void msch_isr(pipe_handle_t pipe_hdl, xfer_result_t event, uint32_t xferred_bytes); void msch_close(uint8_t dev_addr); #endif diff --git a/src/common/tusb_types.h b/src/common/tusb_types.h index 32632cd90..7b5268d4f 100644 --- a/src/common/tusb_types.h +++ b/src/common/tusb_types.h @@ -197,11 +197,10 @@ typedef enum typedef enum { - TUSB_EVENT_NONE = 0, TUSB_EVENT_XFER_COMPLETE, TUSB_EVENT_XFER_ERROR, TUSB_EVENT_XFER_STALLED, -}tusb_event_t; +}xfer_result_t; enum { diff --git a/src/device/usbd.c b/src/device/usbd.c index f39605987..710eba553 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -92,7 +92,7 @@ typedef struct { tusb_error_t (* open ) (uint8_t rhport, tusb_desc_interface_t const * desc_intf, uint16_t* p_length); bool (* control_request ) (uint8_t rhport, tusb_control_request_t const * request); bool (* control_request_complete ) (uint8_t rhport, tusb_control_request_t const * request); - tusb_error_t (* xfer_cb ) (uint8_t rhport, uint8_t ep_addr, tusb_event_t, uint32_t); + tusb_error_t (* xfer_cb ) (uint8_t rhport, uint8_t ep_addr, xfer_result_t, uint32_t); void (* sof ) (uint8_t rhport); void (* reset ) (uint8_t); } usbd_class_driver_t; @@ -174,7 +174,7 @@ static bool process_set_config(uint8_t rhport, uint8_t config_number); static void const* get_descriptor(tusb_control_request_t const * p_request, uint16_t* desc_len); void usbd_control_reset (uint8_t rhport); -bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, tusb_event_t event, uint32_t xferred_bytes); +bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); void usbd_control_set_complete_callback( bool (*fp) (uint8_t, tusb_control_request_t const * ) ); //--------------------------------------------------------------------+ diff --git a/src/device/usbd_control.c b/src/device/usbd_control.c index 33de6d064..31d74edf0 100644 --- a/src/device/usbd_control.c +++ b/src/device/usbd_control.c @@ -126,7 +126,7 @@ bool usbd_control_xfer(uint8_t rhport, tusb_control_request_t const * request, v } // callback when a transaction complete on DATA stage of control endpoint -bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, tusb_event_t event, uint32_t xferred_bytes) +bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) { if ( _control_state.request.bmRequestType_bit.direction == TUSB_DIR_OUT ) { diff --git a/src/host/ehci/ehci.c b/src/host/ehci/ehci.c index b3d897537..2fc99ffcd 100644 --- a/src/host/ehci/ehci.c +++ b/src/host/ehci/ehci.c @@ -638,7 +638,7 @@ static void qhd_xfer_error_isr(ehci_qhd_t * p_qhd) qhd_has_xact_error(p_qhd) ) { // current qhd has error in transaction tusb_xfer_type_t const xfer_type = qhd_get_xfer_type(p_qhd); - tusb_event_t error_event; + xfer_result_t error_event; // no error bits are set, endpoint is halted due to STALL error_event = qhd_has_xact_error(p_qhd) ? TUSB_EVENT_XFER_ERROR : TUSB_EVENT_XFER_STALLED; diff --git a/src/host/hub.c b/src/host/hub.c index e4c08c9d1..9635bcc0b 100644 --- a/src/host/hub.c +++ b/src/host/hub.c @@ -209,7 +209,7 @@ tusb_error_t hub_open_subtask(uint8_t dev_addr, tusb_desc_interface_t const *p_i } // is the response of interrupt endpoint polling -void hub_isr(pipe_handle_t pipe_hdl, tusb_event_t event, uint32_t xferred_bytes) +void hub_isr(pipe_handle_t pipe_hdl, xfer_result_t event, uint32_t xferred_bytes) { (void) xferred_bytes; // TODO can be more than 1 for hub with lots of ports diff --git a/src/host/hub.h b/src/host/hub.h index 67c02f2e3..9376a2698 100644 --- a/src/host/hub.h +++ b/src/host/hub.h @@ -196,7 +196,7 @@ tusb_error_t hub_status_pipe_queue(uint8_t dev_addr); void hub_init(void); tusb_error_t hub_open_subtask(uint8_t dev_addr, tusb_desc_interface_t const *p_interface_desc, uint16_t *p_length) ATTR_WARN_UNUSED_RESULT; -void hub_isr(pipe_handle_t pipe_hdl, tusb_event_t event, uint32_t xferred_bytes); +void hub_isr(pipe_handle_t pipe_hdl, xfer_result_t event, uint32_t xferred_bytes); void hub_close(uint8_t dev_addr); #endif diff --git a/src/host/ohci/ohci.c b/src/host/ohci/ohci.c index f058f8348..58738a236 100644 --- a/src/host/ohci/ohci.c +++ b/src/host/ohci/ohci.c @@ -617,7 +617,7 @@ static void done_queue_isr(uint8_t hostid) // TODO check if td_head is iso td //------------- Non ISO transfer -------------// ohci_gtd_t * const p_qtd = (ohci_gtd_t *) td_head; - tusb_event_t const event = (p_qtd->condition_code == OHCI_CCODE_NO_ERROR) ? TUSB_EVENT_XFER_COMPLETE : + xfer_result_t const event = (p_qtd->condition_code == OHCI_CCODE_NO_ERROR) ? TUSB_EVENT_XFER_COMPLETE : (p_qtd->condition_code == OHCI_CCODE_STALL) ? TUSB_EVENT_XFER_STALLED : TUSB_EVENT_XFER_ERROR; p_qtd->used = 0; // free TD diff --git a/src/host/usbh.c b/src/host/usbh.c index 196a45ee7..ed21bf3da 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -256,7 +256,7 @@ static inline uint8_t std_class_code_to_index(uint8_t std_class_code) // USBH-HCD ISR/Callback API //--------------------------------------------------------------------+ // interrupt caused by a TD (with IOC=1) in pipe of class class_code -void usbh_xfer_isr(pipe_handle_t pipe_hdl, uint8_t class_code, tusb_event_t event, uint32_t xferred_bytes) +void usbh_xfer_isr(pipe_handle_t pipe_hdl, uint8_t class_code, xfer_result_t event, uint32_t xferred_bytes) { uint8_t class_index = std_class_code_to_index(class_code); if (TUSB_XFER_CONTROL == pipe_hdl.xfer_type) diff --git a/src/host/usbh.h b/src/host/usbh.h index 5aaeb4186..22fdef162 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -66,7 +66,7 @@ typedef enum tusb_interface_status_{ typedef struct { void (* const init) (void); tusb_error_t (* const open_subtask)(uint8_t, tusb_desc_interface_t const *, uint16_t*); - void (* const isr) (pipe_handle_t, tusb_event_t, uint32_t); + void (* const isr) (pipe_handle_t, xfer_result_t, uint32_t); void (* const close) (uint8_t); } host_class_driver_t; //--------------------------------------------------------------------+ diff --git a/src/host/usbh_hcd.h b/src/host/usbh_hcd.h index 1c2c4ad0b..f6b72273a 100644 --- a/src/host/usbh_hcd.h +++ b/src/host/usbh_hcd.h @@ -101,7 +101,7 @@ extern usbh_device_info_t usbh_devices[CFG_TUSB_HOST_DEVICE_MAX+1]; // including //--------------------------------------------------------------------+ // callback from HCD ISR //--------------------------------------------------------------------+ -void usbh_xfer_isr(pipe_handle_t pipe_hdl, uint8_t class_code, tusb_event_t event, uint32_t xferred_bytes); +void usbh_xfer_isr(pipe_handle_t pipe_hdl, uint8_t class_code, xfer_result_t event, uint32_t xferred_bytes); void usbh_hcd_rhport_plugged_isr(uint8_t hostid); void usbh_hcd_rhport_unplugged_isr(uint8_t hostid); diff --git a/tests/lpc18xx_43xx/test/host/cdc/cdc_callback.h b/tests/lpc18xx_43xx/test/host/cdc/cdc_callback.h index b1aea64b0..1eb608b91 100644 --- a/tests/lpc18xx_43xx/test/host/cdc/cdc_callback.h +++ b/tests/lpc18xx_43xx/test/host/cdc/cdc_callback.h @@ -55,7 +55,7 @@ void tusbh_cdc_mounted_cb(uint8_t dev_addr); void tusbh_cdc_unmounted_cb(uint8_t dev_addr); -void tusbh_cdc_xfer_isr(uint8_t dev_addr, tusb_event_t event, cdc_pipeid_t pipe_id, uint32_t xferred_bytes); +void tusbh_cdc_xfer_isr(uint8_t dev_addr, xfer_result_t event, cdc_pipeid_t pipe_id, uint32_t xferred_bytes); void tusbh_cdc_rndis_mounted_cb(uint8_t dev_addr); void tusbh_cdc_rndis_unmounted_isr(uint8_t dev_addr); diff --git a/tests/lpc18xx_43xx/test/host/hid/hidh_callback.h b/tests/lpc18xx_43xx/test/host/hid/hidh_callback.h index 4b76bd3cd..b0945c1d1 100644 --- a/tests/lpc18xx_43xx/test/host/hid/hidh_callback.h +++ b/tests/lpc18xx_43xx/test/host/hid/hidh_callback.h @@ -59,11 +59,11 @@ #include "common/common.h" //------------- hidh -------------// -void tusbh_hid_keyboard_isr(uint8_t dev_addr, tusb_event_t event); +void tusbh_hid_keyboard_isr(uint8_t dev_addr, xfer_result_t event); void tusbh_hid_keyboard_mounted_cb(uint8_t dev_addr); void tusbh_hid_keyboard_unmounted_cb(uint8_t dev_addr); -void tusbh_hid_mouse_isr(uint8_t dev_addr, tusb_event_t event); +void tusbh_hid_mouse_isr(uint8_t dev_addr, xfer_result_t event); void tusbh_hid_mouse_mounted_cb(uint8_t dev_addr); void tusbh_hid_mouse_unmounted_cb(uint8_t dev_addr); diff --git a/tests/lpc18xx_43xx/test/host/msc/msch_callback.h b/tests/lpc18xx_43xx/test/host/msc/msch_callback.h index 26b301a00..275245bec 100644 --- a/tests/lpc18xx_43xx/test/host/msc/msch_callback.h +++ b/tests/lpc18xx_43xx/test/host/msc/msch_callback.h @@ -54,7 +54,7 @@ void tusbh_msc_mounted_cb(uint8_t dev_addr); void tusbh_msc_unmounted_cb(uint8_t dev_addr); -void tusbh_msc_isr(uint8_t dev_addr, tusb_event_t event, uint32_t xferred_bytes); +void tusbh_msc_isr(uint8_t dev_addr, xfer_result_t event, uint32_t xferred_bytes); #ifdef __cplusplus -- cgit v1.3.1 From a619ff88a36e4b841cb5901135b1811b06c3c843 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 23 Nov 2018 15:17:43 +0700 Subject: rename xfer complete enum --- examples/obsolete/device/src/keyboard_device_app.c | 6 +++--- examples/obsolete/device/src/mouse_device_app.c | 6 +++--- examples/obsolete/host/src/cdc_serial_host_app.c | 6 +++--- examples/obsolete/host/src/keyboard_host_app.c | 4 ++-- examples/obsolete/host/src/mouse_host_app.c | 4 ++-- src/class/cdc/cdc_host.h | 6 +++--- src/class/hid/hid_host.h | 12 ++++++------ src/class/msc/msc_host.h | 6 +++--- src/common/tusb_types.h | 6 +++--- src/host/ehci/ehci.c | 6 +++--- src/host/hub.c | 2 +- src/host/ohci/ohci.c | 10 +++++----- src/host/usbh.c | 8 ++++---- src/osal/osal_none.h | 6 ++++-- tests/lpc18xx_43xx/test/host/cdc/test_cdc_host.c | 12 ++++++------ tests/lpc18xx_43xx/test/host/cdc/test_cdc_rndis_host.c | 2 +- tests/lpc18xx_43xx/test/host/ehci/test_pipe_bulk_xfer.c | 2 +- tests/lpc18xx_43xx/test/host/ehci/test_pipe_control_xfer.c | 6 +++--- tests/lpc18xx_43xx/test/host/ehci/test_pipe_interrupt_xfer.c | 6 +++--- tests/lpc18xx_43xx/test/host/hid/test_hidh_keyboard.c | 4 ++-- tests/lpc18xx_43xx/test/host/hid/test_hidh_mouse.c | 8 ++++---- tests/lpc18xx_43xx/test/host/usbh/test_enum_task.c | 2 +- 22 files changed, 66 insertions(+), 64 deletions(-) (limited to 'src/common') diff --git a/examples/obsolete/device/src/keyboard_device_app.c b/examples/obsolete/device/src/keyboard_device_app.c index 6c413464e..5e14c56c9 100644 --- a/examples/obsolete/device/src/keyboard_device_app.c +++ b/examples/obsolete/device/src/keyboard_device_app.c @@ -70,9 +70,9 @@ void tud_hid_keyboard_cb(uint8_t rhport, xfer_result_t event, uint32_t xferred_b { switch(event) { - case TUSB_EVENT_XFER_COMPLETE: - case TUSB_EVENT_XFER_ERROR: - case TUSB_EVENT_XFER_STALLED: + case XFER_RESULT_SUCCESS: + case XFER_RESULT_FAILED: + case XFER_RESULT_STALLED: default: break; } } diff --git a/examples/obsolete/device/src/mouse_device_app.c b/examples/obsolete/device/src/mouse_device_app.c index 4c4d322d7..6869f1a05 100644 --- a/examples/obsolete/device/src/mouse_device_app.c +++ b/examples/obsolete/device/src/mouse_device_app.c @@ -70,9 +70,9 @@ void tud_hid_mouse_cb(uint8_t rhport, xfer_result_t event, uint32_t xferred_byte { switch(event) { - case TUSB_EVENT_XFER_COMPLETE: - case TUSB_EVENT_XFER_ERROR: - case TUSB_EVENT_XFER_STALLED: + case XFER_RESULT_SUCCESS: + case XFER_RESULT_FAILED: + case XFER_RESULT_STALLED: default: break; } } diff --git a/examples/obsolete/host/src/cdc_serial_host_app.c b/examples/obsolete/host/src/cdc_serial_host_app.c index afb2b8937..85604dcdf 100644 --- a/examples/obsolete/host/src/cdc_serial_host_app.c +++ b/examples/obsolete/host/src/cdc_serial_host_app.c @@ -84,17 +84,17 @@ void tuh_cdc_xfer_isr(uint8_t dev_addr, xfer_result_t event, cdc_pipeid_t pipe_i case CDC_PIPE_DATA_IN: switch(event) { - case TUSB_EVENT_XFER_COMPLETE: + case XFER_RESULT_SUCCESS: received_bytes = xferred_bytes; osal_semaphore_post(sem_hdl); // notify main task break; - case TUSB_EVENT_XFER_ERROR: + case XFER_RESULT_FAILED: received_bytes = 0; // ignore tuh_cdc_receive(dev_addr, serial_in_buffer, SERIAL_BUFFER_SIZE, true); // waiting for next data break; - case TUSB_EVENT_XFER_STALLED: + case XFER_RESULT_STALLED: default : break; } diff --git a/examples/obsolete/host/src/keyboard_host_app.c b/examples/obsolete/host/src/keyboard_host_app.c index 27d10b9e7..fd51548c3 100644 --- a/examples/obsolete/host/src/keyboard_host_app.c +++ b/examples/obsolete/host/src/keyboard_host_app.c @@ -81,12 +81,12 @@ void tuh_hid_keyboard_isr(uint8_t dev_addr, xfer_result_t event) { switch(event) { - case TUSB_EVENT_XFER_COMPLETE: + case XFER_RESULT_SUCCESS: osal_queue_send(queue_kbd_hdl, &usb_keyboard_report); tuh_hid_keyboard_get_report(dev_addr, (uint8_t*) &usb_keyboard_report); break; - case TUSB_EVENT_XFER_ERROR: + case XFER_RESULT_FAILED: tuh_hid_keyboard_get_report(dev_addr, (uint8_t*) &usb_keyboard_report); // ignore & continue break; diff --git a/examples/obsolete/host/src/mouse_host_app.c b/examples/obsolete/host/src/mouse_host_app.c index 05135693b..819c2b290 100644 --- a/examples/obsolete/host/src/mouse_host_app.c +++ b/examples/obsolete/host/src/mouse_host_app.c @@ -80,12 +80,12 @@ void tuh_hid_mouse_isr(uint8_t dev_addr, xfer_result_t event) { switch(event) { - case TUSB_EVENT_XFER_COMPLETE: + case XFER_RESULT_SUCCESS: osal_queue_send(queue_mouse_hdl, &usb_mouse_report); (void) tuh_hid_mouse_get_report(dev_addr, (uint8_t*) &usb_mouse_report); break; - case TUSB_EVENT_XFER_ERROR: + case XFER_RESULT_FAILED: (void) tuh_hid_mouse_get_report(dev_addr, (uint8_t*) &usb_mouse_report); // ignore & continue break; diff --git a/src/class/cdc/cdc_host.h b/src/class/cdc/cdc_host.h index 8cfe6e5b7..0b863bb61 100644 --- a/src/class/cdc/cdc_host.h +++ b/src/class/cdc/cdc_host.h @@ -122,9 +122,9 @@ void tuh_cdc_unmounted_cb(uint8_t dev_addr); * \param[in] pipe_id value from \ref cdc_pipeid_t indicate the pipe * \param[in] xferred_bytes Number of bytes transferred via USB bus * \note event can be one of following - * - TUSB_EVENT_XFER_COMPLETE : previously scheduled transfer completes successfully. - * - TUSB_EVENT_XFER_ERROR : previously scheduled transfer encountered a transaction error. - * - TUSB_EVENT_XFER_STALLED : previously scheduled transfer is stalled by device. + * - XFER_RESULT_SUCCESS : previously scheduled transfer completes successfully. + * - XFER_RESULT_FAILED : previously scheduled transfer encountered a transaction error. + * - XFER_RESULT_STALLED : previously scheduled transfer is stalled by device. * \note */ void tuh_cdc_xfer_isr(uint8_t dev_addr, xfer_result_t event, cdc_pipeid_t pipe_id, uint32_t xferred_bytes); diff --git a/src/class/hid/hid_host.h b/src/class/hid/hid_host.h index fb10a614f..cb0230e8a 100644 --- a/src/class/hid/hid_host.h +++ b/src/class/hid/hid_host.h @@ -95,9 +95,9 @@ tusb_error_t tuh_hid_keyboard_get_report(uint8_t dev_addr, void * p_report) /*A * \param[in] dev_addr Address of device * \param[in] event an value from \ref xfer_result_t * \note event can be one of following - * - TUSB_EVENT_XFER_COMPLETE : previously scheduled transfer completes successfully. - * - TUSB_EVENT_XFER_ERROR : previously scheduled transfer encountered a transaction error. - * - TUSB_EVENT_XFER_STALLED : previously scheduled transfer is stalled by device. + * - XFER_RESULT_SUCCESS : previously scheduled transfer completes successfully. + * - XFER_RESULT_FAILED : previously scheduled transfer encountered a transaction error. + * - XFER_RESULT_STALLED : previously scheduled transfer is stalled by device. * \note Application should schedule the next report by calling \ref tuh_hid_keyboard_get_report within this callback */ void tuh_hid_keyboard_isr(uint8_t dev_addr, xfer_result_t event); @@ -160,9 +160,9 @@ tusb_error_t tuh_hid_mouse_get_report(uint8_t dev_addr, void* p_report) /*ATTR_ * \param[in] dev_addr Address of device * \param[in] event an value from \ref xfer_result_t * \note event can be one of following - * - TUSB_EVENT_XFER_COMPLETE : previously scheduled transfer completes successfully. - * - TUSB_EVENT_XFER_ERROR : previously scheduled transfer encountered a transaction error. - * - TUSB_EVENT_XFER_STALLED : previously scheduled transfer is stalled by device. + * - XFER_RESULT_SUCCESS : previously scheduled transfer completes successfully. + * - XFER_RESULT_FAILED : previously scheduled transfer encountered a transaction error. + * - XFER_RESULT_STALLED : previously scheduled transfer is stalled by device. * \note Application should schedule the next report by calling \ref tuh_hid_mouse_get_report within this callback */ void tuh_hid_mouse_isr(uint8_t dev_addr, xfer_result_t event); diff --git a/src/class/msc/msc_host.h b/src/class/msc/msc_host.h index 0afe5c515..a408bbeaf 100644 --- a/src/class/msc/msc_host.h +++ b/src/class/msc/msc_host.h @@ -174,9 +174,9 @@ void tuh_msc_unmounted_cb(uint8_t dev_addr); * \param[in] event an value from \ref xfer_result_t * \param[in] xferred_bytes Number of bytes transferred via USB bus * \note event can be one of following - * - TUSB_EVENT_XFER_COMPLETE : previously scheduled transfer completes successfully. - * - TUSB_EVENT_XFER_ERROR : previously scheduled transfer encountered a transaction error. - * - TUSB_EVENT_XFER_STALLED : previously scheduled transfer is stalled by device. + * - XFER_RESULT_SUCCESS : previously scheduled transfer completes successfully. + * - XFER_RESULT_FAILED : previously scheduled transfer encountered a transaction error. + * - XFER_RESULT_STALLED : previously scheduled transfer is stalled by device. * \note */ void tuh_msc_isr(uint8_t dev_addr, xfer_result_t event, uint32_t xferred_bytes); diff --git a/src/common/tusb_types.h b/src/common/tusb_types.h index 7b5268d4f..9c3c21b88 100644 --- a/src/common/tusb_types.h +++ b/src/common/tusb_types.h @@ -197,9 +197,9 @@ typedef enum typedef enum { - TUSB_EVENT_XFER_COMPLETE, - TUSB_EVENT_XFER_ERROR, - TUSB_EVENT_XFER_STALLED, + XFER_RESULT_SUCCESS, + XFER_RESULT_FAILED, + XFER_RESULT_STALLED, }xfer_result_t; enum diff --git a/src/host/ehci/ehci.c b/src/host/ehci/ehci.c index 2fc99ffcd..27808d59b 100644 --- a/src/host/ehci/ehci.c +++ b/src/host/ehci/ehci.c @@ -570,7 +570,7 @@ static void qhd_xfer_complete_isr(ehci_qhd_t * p_qhd) if (is_ioc) // end of request { // call USBH callback usbh_xfer_isr( qhd_create_pipe_handle(p_qhd, xfer_type), - p_qhd->class_code, TUSB_EVENT_XFER_COMPLETE, + p_qhd->class_code, XFER_RESULT_SUCCESS, p_qhd->total_xferred_bytes - (xfer_type == TUSB_XFER_CONTROL ? 8 : 0) ); // subtract setup packet size if control, p_qhd->total_xferred_bytes = 0; } @@ -641,12 +641,12 @@ static void qhd_xfer_error_isr(ehci_qhd_t * p_qhd) xfer_result_t error_event; // no error bits are set, endpoint is halted due to STALL - error_event = qhd_has_xact_error(p_qhd) ? TUSB_EVENT_XFER_ERROR : TUSB_EVENT_XFER_STALLED; + error_event = qhd_has_xact_error(p_qhd) ? XFER_RESULT_FAILED : XFER_RESULT_STALLED; p_qhd->total_xferred_bytes += p_qhd->p_qtd_list_head->expected_bytes - p_qhd->p_qtd_list_head->total_bytes; -// if ( TUSB_EVENT_XFER_ERROR == error_event ) TU_BREAKPOINT(); // TODO skip unplugged device +// if ( XFER_RESULT_FAILED == error_event ) TU_BREAKPOINT(); // TODO skip unplugged device p_qhd->p_qtd_list_head->used = 0; // free QTD qtd_remove_1st_from_qhd(p_qhd); diff --git a/src/host/hub.c b/src/host/hub.c index 9635bcc0b..55c8597ad 100644 --- a/src/host/hub.c +++ b/src/host/hub.c @@ -215,7 +215,7 @@ void hub_isr(pipe_handle_t pipe_hdl, xfer_result_t event, uint32_t xferred_bytes usbh_hub_t * p_hub = &hub_data[pipe_hdl.dev_addr-1]; - if ( event == TUSB_EVENT_XFER_COMPLETE ) + if ( event == XFER_RESULT_SUCCESS ) { for (uint8_t port=1; port <= p_hub->port_number; port++) { // TODO HUB ignore bit0 hub_status_change diff --git a/src/host/ohci/ohci.c b/src/host/ohci/ohci.c index 58738a236..91d9b6243 100644 --- a/src/host/ohci/ohci.c +++ b/src/host/ohci/ohci.c @@ -617,11 +617,11 @@ static void done_queue_isr(uint8_t hostid) // TODO check if td_head is iso td //------------- Non ISO transfer -------------// ohci_gtd_t * const p_qtd = (ohci_gtd_t *) td_head; - xfer_result_t const event = (p_qtd->condition_code == OHCI_CCODE_NO_ERROR) ? TUSB_EVENT_XFER_COMPLETE : - (p_qtd->condition_code == OHCI_CCODE_STALL) ? TUSB_EVENT_XFER_STALLED : TUSB_EVENT_XFER_ERROR; + xfer_result_t const event = (p_qtd->condition_code == OHCI_CCODE_NO_ERROR) ? XFER_RESULT_SUCCESS : + (p_qtd->condition_code == OHCI_CCODE_STALL) ? XFER_RESULT_STALLED : XFER_RESULT_FAILED; p_qtd->used = 0; // free TD - if ( (p_qtd->delay_interrupt == OHCI_INT_ON_COMPLETE_YES) || (event != TUSB_EVENT_XFER_COMPLETE) ) + if ( (p_qtd->delay_interrupt == OHCI_INT_ON_COMPLETE_YES) || (event != XFER_RESULT_SUCCESS) ) { ohci_ed_t * const p_ed = gtd_get_ed(p_qtd); @@ -634,11 +634,11 @@ static void done_queue_isr(uint8_t hostid) // --> HC will not process Control list (due to service ratio when Bulk list not empty) // To walk-around this, the halted ED will have TailP = HeadP (empty list condition), when clearing halt // the TailP must be set back to NULL for processing remaining TDs - if ((event != TUSB_EVENT_XFER_COMPLETE)) + if ((event != XFER_RESULT_SUCCESS)) { p_ed->td_tail.address &= 0x0Ful; p_ed->td_tail.address |= tu_align16(p_ed->td_head.address); // mark halted EP as empty queue - if ( event == TUSB_EVENT_XFER_STALLED ) p_ed->is_stalled = 1; + if ( event == XFER_RESULT_STALLED ) p_ed->is_stalled = 1; } pipe_handle_t pipe_hdl = diff --git a/src/host/usbh.c b/src/host/usbh.c index ed21bf3da..a0aab3b96 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -199,7 +199,7 @@ tusb_error_t usbh_control_xfer_subtask(uint8_t dev_addr, uint8_t bmRequestType, #ifndef _TEST_ usbh_devices[dev_addr].control.pipe_status = 0; #else - usbh_devices[dev_addr].control.pipe_status = TUSB_EVENT_XFER_COMPLETE; // in Test project, mark as complete immediately + usbh_devices[dev_addr].control.pipe_status = XFER_RESULT_SUCCESS; // in Test project, mark as complete immediately #endif error = hcd_pipe_control_xfer(dev_addr, &usbh_devices[dev_addr].control.request, data); @@ -207,11 +207,11 @@ tusb_error_t usbh_control_xfer_subtask(uint8_t dev_addr, uint8_t bmRequestType, osal_mutex_release(usbh_devices[dev_addr].control.mutex_hdl); STASK_ASSERT_ERR(error); - if (TUSB_EVENT_XFER_STALLED == usbh_devices[dev_addr].control.pipe_status) STASK_RETURN(TUSB_ERROR_USBH_XFER_STALLED); - if (TUSB_EVENT_XFER_ERROR == usbh_devices[dev_addr].control.pipe_status) STASK_RETURN(TUSB_ERROR_USBH_XFER_FAILED); + if (XFER_RESULT_STALLED == usbh_devices[dev_addr].control.pipe_status) STASK_RETURN(TUSB_ERROR_USBH_XFER_STALLED); + if (XFER_RESULT_FAILED == usbh_devices[dev_addr].control.pipe_status) STASK_RETURN(TUSB_ERROR_USBH_XFER_FAILED); // STASK_ASSERT_HDLR(TUSB_ERROR_NONE == error && -// TUSB_EVENT_XFER_COMPLETE == usbh_devices[dev_addr].control.pipe_status, +// XFER_RESULT_SUCCESS == usbh_devices[dev_addr].control.pipe_status, // tuh_device_mount_failed_cb(TUSB_ERROR_USBH_MOUNT_DEVICE_NOT_RESPOND, NULL) ); OSAL_SUBTASK_END diff --git a/src/osal/osal_none.h b/src/osal/osal_none.h index 46930aeda..b21c3332a 100644 --- a/src/osal/osal_none.h +++ b/src/osal/osal_none.h @@ -156,10 +156,12 @@ static inline void osal_queue_reset(osal_queue_t const queue_hdl) static inline bool osal_queue_receive(osal_queue_t const queue_hdl, void* data) { // osal none return immediately without blocking + // extern void tusb_hal_int_disable(uint8_t rhport); + // extern void tusb_hal_int_enable(uint8_t rhport); - // tusb_hal_int_disable_all(); +// tusb_hal_int_disable(0); bool rc = tu_fifo_read(queue_hdl, data); - // tusb_hal_int_enable_all(); +// tusb_hal_int_enable(0); return rc; } diff --git a/tests/lpc18xx_43xx/test/host/cdc/test_cdc_host.c b/tests/lpc18xx_43xx/test/host/cdc/test_cdc_host.c index 5077eea93..12dce0528 100644 --- a/tests/lpc18xx_43xx/test/host/cdc/test_cdc_host.c +++ b/tests/lpc18xx_43xx/test/host/cdc/test_cdc_host.c @@ -251,10 +251,10 @@ void test_cdc_xfer_notification_pipe(void) cdch_data[dev_addr-1].pipe_out = pipe_out; cdch_data[dev_addr-1].pipe_in = pipe_in; - tusbh_cdc_xfer_isr_Expect(dev_addr, TUSB_EVENT_XFER_COMPLETE, CDC_PIPE_NOTIFICATION, 10); + tusbh_cdc_xfer_isr_Expect(dev_addr, XFER_RESULT_SUCCESS, CDC_PIPE_NOTIFICATION, 10); //------------- CUT -------------// - cdch_isr(pipe_notification, TUSB_EVENT_XFER_COMPLETE, 10); + cdch_isr(pipe_notification, XFER_RESULT_SUCCESS, 10); } void test_cdc_xfer_pipe_out(void) @@ -267,10 +267,10 @@ void test_cdc_xfer_pipe_out(void) cdch_data[dev_addr-1].pipe_out = pipe_out; cdch_data[dev_addr-1].pipe_in = pipe_in; - tusbh_cdc_xfer_isr_Expect(dev_addr, TUSB_EVENT_XFER_ERROR, CDC_PIPE_DATA_OUT, 20); + tusbh_cdc_xfer_isr_Expect(dev_addr, XFER_RESULT_FAILED, CDC_PIPE_DATA_OUT, 20); //------------- CUT -------------// - cdch_isr(pipe_out, TUSB_EVENT_XFER_ERROR, 20); + cdch_isr(pipe_out, XFER_RESULT_FAILED, 20); } void test_cdc_xfer_pipe_in(void) @@ -283,8 +283,8 @@ void test_cdc_xfer_pipe_in(void) cdch_data[dev_addr-1].pipe_out = pipe_out; cdch_data[dev_addr-1].pipe_in = pipe_in; - tusbh_cdc_xfer_isr_Expect(dev_addr, TUSB_EVENT_XFER_STALLED, CDC_PIPE_DATA_IN, 0); + tusbh_cdc_xfer_isr_Expect(dev_addr, XFER_RESULT_STALLED, CDC_PIPE_DATA_IN, 0); //------------- CUT -------------// - cdch_isr(pipe_in, TUSB_EVENT_XFER_STALLED, 0); + cdch_isr(pipe_in, XFER_RESULT_STALLED, 0); } diff --git a/tests/lpc18xx_43xx/test/host/cdc/test_cdc_rndis_host.c b/tests/lpc18xx_43xx/test/host/cdc/test_cdc_rndis_host.c index a493c3b79..86d6c2890 100644 --- a/tests/lpc18xx_43xx/test/host/cdc/test_cdc_rndis_host.c +++ b/tests/lpc18xx_43xx/test/host/cdc/test_cdc_rndis_host.c @@ -188,7 +188,7 @@ static tusb_error_t stub_pipe_notification_xfer(pipe_handle_t pipe_hdl, uint8_t buffer[0] = 1; // response available - cdch_isr(pipe_hdl, TUSB_EVENT_XFER_COMPLETE, 8); + cdch_isr(pipe_hdl, XFER_RESULT_SUCCESS, 8); return TUSB_ERROR_NONE; } diff --git a/tests/lpc18xx_43xx/test/host/ehci/test_pipe_bulk_xfer.c b/tests/lpc18xx_43xx/test/host/ehci/test_pipe_bulk_xfer.c index 2e9e29fdc..c4037c596 100644 --- a/tests/lpc18xx_43xx/test/host/ehci/test_pipe_bulk_xfer.c +++ b/tests/lpc18xx_43xx/test/host/ehci/test_pipe_bulk_xfer.c @@ -208,7 +208,7 @@ void test_bulk_xfer_complete_isr(void) ehci_qtd_t* p_head = p_qhd_bulk->p_qtd_list_head; ehci_qtd_t* p_tail = p_qhd_bulk->p_qtd_list_tail; - usbh_xfer_isr_Expect(pipe_hdl_bulk, TUSB_CLASS_MSC, TUSB_EVENT_XFER_COMPLETE, sizeof(data2)+sizeof(xfer_data)); + usbh_xfer_isr_Expect(pipe_hdl_bulk, TUSB_CLASS_MSC, XFER_RESULT_SUCCESS, sizeof(data2)+sizeof(xfer_data)); //------------- Code Under Test -------------// ehci_controller_run(hostid); diff --git a/tests/lpc18xx_43xx/test/host/ehci/test_pipe_control_xfer.c b/tests/lpc18xx_43xx/test/host/ehci/test_pipe_control_xfer.c index ffd7ffb67..4f8cdb4c8 100644 --- a/tests/lpc18xx_43xx/test/host/ehci/test_pipe_control_xfer.c +++ b/tests/lpc18xx_43xx/test/host/ehci/test_pipe_control_xfer.c @@ -228,7 +228,7 @@ void test_control_xfer_complete_isr(void) { TEST_ASSERT_STATUS( hcd_pipe_control_xfer(dev_addr, &request_get_dev_desc, xfer_data) ); - usbh_xfer_isr_Expect(((pipe_handle_t){.dev_addr = dev_addr}), 0, TUSB_EVENT_XFER_COMPLETE, 18); + usbh_xfer_isr_Expect(((pipe_handle_t){.dev_addr = dev_addr}), 0, XFER_RESULT_SUCCESS, 18); //------------- Code Under TEST -------------// ehci_controller_run(hostid); @@ -247,7 +247,7 @@ void test_control_xfer_error_isr(void) { TEST_ASSERT_STATUS( hcd_pipe_control_xfer(dev_addr, &request_get_dev_desc, xfer_data) ); - usbh_xfer_isr_Expect(((pipe_handle_t){.dev_addr = dev_addr}), 0, TUSB_EVENT_XFER_ERROR, 0); + usbh_xfer_isr_Expect(((pipe_handle_t){.dev_addr = dev_addr}), 0, XFER_RESULT_FAILED, 0); //------------- Code Under TEST -------------// ehci_controller_run_error(hostid); @@ -266,7 +266,7 @@ void test_control_xfer_error_stall(void) { TEST_ASSERT_STATUS( hcd_pipe_control_xfer(dev_addr, &request_get_dev_desc, xfer_data) ); - usbh_xfer_isr_Expect(((pipe_handle_t){.dev_addr = dev_addr}), 0, TUSB_EVENT_XFER_STALLED, 0); + usbh_xfer_isr_Expect(((pipe_handle_t){.dev_addr = dev_addr}), 0, XFER_RESULT_STALLED, 0); //------------- Code Under TEST -------------// ehci_controller_run_stall(hostid); diff --git a/tests/lpc18xx_43xx/test/host/ehci/test_pipe_interrupt_xfer.c b/tests/lpc18xx_43xx/test/host/ehci/test_pipe_interrupt_xfer.c index 827db2897..bf7ad352a 100644 --- a/tests/lpc18xx_43xx/test/host/ehci/test_pipe_interrupt_xfer.c +++ b/tests/lpc18xx_43xx/test/host/ehci/test_pipe_interrupt_xfer.c @@ -201,7 +201,7 @@ void test_interrupt_xfer_complete_isr_interval_less_than_1ms(void) TEST_ASSERT_STATUS( hcd_pipe_xfer(pipe_hdl_interrupt, data2, sizeof(data2), true) ); - usbh_xfer_isr_Expect(pipe_hdl_interrupt, TUSB_CLASS_HID, TUSB_EVENT_XFER_COMPLETE, sizeof(xfer_data)+sizeof(data2)); + usbh_xfer_isr_Expect(pipe_hdl_interrupt, TUSB_CLASS_HID, XFER_RESULT_SUCCESS, sizeof(xfer_data)+sizeof(data2)); ehci_qtd_t* p_head = p_qhd_interrupt->p_qtd_list_head; ehci_qtd_t* p_tail = p_qhd_interrupt->p_qtd_list_tail; @@ -242,7 +242,7 @@ void test_interrupt_xfer_error_isr(void) { TEST_ASSERT_STATUS( hcd_pipe_xfer(pipe_hdl_interrupt, xfer_data, sizeof(xfer_data), true) ); - usbh_xfer_isr_Expect(pipe_hdl_interrupt, TUSB_CLASS_HID, TUSB_EVENT_XFER_ERROR, 0); + usbh_xfer_isr_Expect(pipe_hdl_interrupt, TUSB_CLASS_HID, XFER_RESULT_FAILED, 0); //------------- Code Under TEST -------------// ehci_controller_run_error(hostid); @@ -254,7 +254,7 @@ void test_interrupt_xfer_error_stall(void) { TEST_ASSERT_STATUS( hcd_pipe_xfer(pipe_hdl_interrupt, xfer_data, sizeof(xfer_data), true) ); - usbh_xfer_isr_Expect(pipe_hdl_interrupt, TUSB_CLASS_HID, TUSB_EVENT_XFER_STALLED, 0); + usbh_xfer_isr_Expect(pipe_hdl_interrupt, TUSB_CLASS_HID, XFER_RESULT_STALLED, 0); //------------- Code Under TEST -------------// ehci_controller_run_stall(hostid); diff --git a/tests/lpc18xx_43xx/test/host/hid/test_hidh_keyboard.c b/tests/lpc18xx_43xx/test/host/hid/test_hidh_keyboard.c index b3b49c172..de3581423 100644 --- a/tests/lpc18xx_43xx/test/host/hid/test_hidh_keyboard.c +++ b/tests/lpc18xx_43xx/test/host/hid/test_hidh_keyboard.c @@ -216,10 +216,10 @@ void test_keyboard_get_ok() void test_keyboard_isr_event_complete(void) { - tusbh_hid_keyboard_isr_Expect(dev_addr, TUSB_EVENT_XFER_COMPLETE); + tusbh_hid_keyboard_isr_Expect(dev_addr, XFER_RESULT_SUCCESS); //------------- Code Under TEST -------------// - hidh_isr(p_hidh_kbd->pipe_hdl, TUSB_EVENT_XFER_COMPLETE, 8); + hidh_isr(p_hidh_kbd->pipe_hdl, XFER_RESULT_SUCCESS, 8); // tusbh_device_get_state_IgnoreAndReturn(TUSB_DEVICE_STATE_CONFIGURED); // TEST_ASSERT_EQUAL(TUSB_INTERFACE_STATUS_COMPLETE, tusbh_hid_keyboard_status(dev_addr)); diff --git a/tests/lpc18xx_43xx/test/host/hid/test_hidh_mouse.c b/tests/lpc18xx_43xx/test/host/hid/test_hidh_mouse.c index b1a3558e6..541c2caef 100644 --- a/tests/lpc18xx_43xx/test/host/hid/test_hidh_mouse.c +++ b/tests/lpc18xx_43xx/test/host/hid/test_hidh_mouse.c @@ -189,10 +189,10 @@ void test_mouse_get_ok() void test_mouse_isr_event_xfer_complete(void) { - tusbh_hid_mouse_isr_Expect(dev_addr, TUSB_EVENT_XFER_COMPLETE); + tusbh_hid_mouse_isr_Expect(dev_addr, XFER_RESULT_SUCCESS); //------------- Code Under TEST -------------// - hidh_isr(p_hidh_mouse->pipe_hdl, TUSB_EVENT_XFER_COMPLETE, 8); + hidh_isr(p_hidh_mouse->pipe_hdl, XFER_RESULT_SUCCESS, 8); tusbh_device_get_state_IgnoreAndReturn(TUSB_DEVICE_STATE_CONFIGURED); // TEST_ASSERT_EQUAL(TUSB_INTERFACE_STATUS_COMPLETE, tusbh_hid_mouse_status(dev_addr)); @@ -200,10 +200,10 @@ void test_mouse_isr_event_xfer_complete(void) void test_mouse_isr_event_xfer_error(void) { - tusbh_hid_mouse_isr_Expect(dev_addr, TUSB_EVENT_XFER_ERROR); + tusbh_hid_mouse_isr_Expect(dev_addr, XFER_RESULT_FAILED); //------------- Code Under TEST -------------// - hidh_isr(p_hidh_mouse->pipe_hdl, TUSB_EVENT_XFER_ERROR, 0); + hidh_isr(p_hidh_mouse->pipe_hdl, XFER_RESULT_FAILED, 0); tusbh_device_get_state_IgnoreAndReturn(TUSB_DEVICE_STATE_CONFIGURED); // TEST_ASSERT_EQUAL(TUSB_INTERFACE_STATUS_ERROR, tusbh_hid_mouse_status(dev_addr)); diff --git a/tests/lpc18xx_43xx/test/host/usbh/test_enum_task.c b/tests/lpc18xx_43xx/test/host/usbh/test_enum_task.c index a85c3c48a..eba3fbcc3 100644 --- a/tests/lpc18xx_43xx/test/host/usbh/test_enum_task.c +++ b/tests/lpc18xx_43xx/test/host/usbh/test_enum_task.c @@ -181,7 +181,7 @@ tusb_error_t control_xfer_stub(uint8_t dev_addr, const tusb_control_request_t * usbh_xfer_isr( (pipe_handle_t) { .dev_addr = (num_call > 1 ? 1 : 0), .xfer_type = TUSB_XFER_CONTROL }, - 0, TUSB_EVENT_XFER_COMPLETE, 0); + 0, XFER_RESULT_SUCCESS, 0); return TUSB_ERROR_NONE; } -- cgit v1.3.1 From 394a22ecf7760cce630a8186260f1c79901af934 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 23 Nov 2018 15:25:25 +0700 Subject: remove pragma GCC diagnostic --- src/class/cdc/cdc.h | 6 ------ src/class/hid/hid.h | 6 ------ src/class/msc/msc.h | 8 +------- src/common/tusb_types.h | 6 ------ 4 files changed, 1 insertion(+), 25 deletions(-) (limited to 'src/common') diff --git a/src/class/cdc/cdc.h b/src/class/cdc/cdc.h index afac8379d..d07c62429 100644 --- a/src/class/cdc/cdc.h +++ b/src/class/cdc/cdc.h @@ -50,10 +50,6 @@ extern "C" { #endif -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wpacked" -#pragma GCC diagnostic ignored "-Wattributes" - /** \defgroup ClassDriver_CDC_Common Common Definitions * @{ */ @@ -406,8 +402,6 @@ typedef struct ATTR_PACKED TU_VERIFY_STATIC(sizeof(cdc_line_control_state_t) == 2, "size is not correct"); -#pragma GCC diagnostic pop - /** @} */ #ifdef __cplusplus diff --git a/src/class/hid/hid.h b/src/class/hid/hid.h index 0008e47fb..8bfede2da 100644 --- a/src/class/hid/hid.h +++ b/src/class/hid/hid.h @@ -49,10 +49,6 @@ extern "C" { #endif -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wpacked" -#pragma GCC diagnostic ignored "-Wattributes" - //--------------------------------------------------------------------+ // Common Definitions //--------------------------------------------------------------------+ @@ -613,8 +609,6 @@ enum HID_USAGE_CONSUMER_AC_PAN = 0x0238, }; -#pragma GCC diagnostic pop - #ifdef __cplusplus } #endif diff --git a/src/class/msc/msc.h b/src/class/msc/msc.h index e7c32b303..10a73bb1c 100644 --- a/src/class/msc/msc.h +++ b/src/class/msc/msc.h @@ -46,16 +46,12 @@ #ifndef _TUSB_MSC_H_ #define _TUSB_MSC_H_ -#include +#include "common/tusb_common.h" #ifdef __cplusplus extern "C" { #endif -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wpacked" -#pragma GCC diagnostic ignored "-Wattributes" - //--------------------------------------------------------------------+ // Mass Storage Class Constant //--------------------------------------------------------------------+ @@ -396,8 +392,6 @@ typedef struct ATTR_PACKED TU_VERIFY_STATIC(sizeof(scsi_read10_t) == 10, "size is not correct"); TU_VERIFY_STATIC(sizeof(scsi_write10_t) == 10, "size is not correct"); -#pragma GCC diagnostic pop - #ifdef __cplusplus } #endif diff --git a/src/common/tusb_types.h b/src/common/tusb_types.h index 9c3c21b88..b11481b18 100644 --- a/src/common/tusb_types.h +++ b/src/common/tusb_types.h @@ -51,10 +51,6 @@ extern "C" { #endif -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wpacked" -#pragma GCC diagnostic ignored "-Wattributes" - /*------------------------------------------------------------------*/ /* CONSTANTS *------------------------------------------------------------------*/ @@ -427,8 +423,6 @@ static inline uint8_t descriptor_len(uint8_t const p_desc[]) // Convert comma-separated string to descriptor unicode format #define TUD_DESC_STRCONV( ... ) (const uint16_t[]) { TUD_DESC_STR_HEADER(VA_ARGS_NUM_(__VA_ARGS__)), __VA_ARGS__ } -#pragma GCC diagnostic pop - #ifdef __cplusplus } #endif -- cgit v1.3.1 From 6f3898572d6f8eb04587f057b74f4f86e8a18856 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 5 Dec 2018 17:01:19 +0700 Subject: add role to OSAL_QUEUE_DEF() to disable correct dcd/hcd isr --- .../device/cdc_msc_hid/ses/samd21/samd21.emProject | 1 + src/common/tusb_fifo.h | 3 +- src/device/usbd.c | 32 ++++---- src/osal/osal_freertos.h | 4 +- src/osal/osal_mynewt.h | 4 +- src/osal/osal_none.h | 89 +++++++++++++++++----- src/tusb_hal.h | 32 -------- src/tusb_option.h | 1 - 8 files changed, 94 insertions(+), 72 deletions(-) (limited to 'src/common') diff --git a/examples/device/cdc_msc_hid/ses/samd21/samd21.emProject b/examples/device/cdc_msc_hid/ses/samd21/samd21.emProject index d61b82cfa..fbb8841b7 100644 --- a/examples/device/cdc_msc_hid/ses/samd21/samd21.emProject +++ b/examples/device/cdc_msc_hid/ses/samd21/samd21.emProject @@ -22,6 +22,7 @@ c_user_include_directories="../../src;$(rootDir)/hw/cmsis/Include;$(rootDir)/hw;$(rootDir)/src;$(asf4Dir);$(asf4Dir)/include;$(asf4Dir)/config;$(asf4Dir)/hri;$(asf4Dir)/hal/include;$(asf4Dir)/hal/utils/include;$(asf4Dir)/hpl/port;$(asf4Dir)/hpl/gclk;$(asf4Dir)/hpl/pm" debug_register_definition_file="ATSAMD21G18A_Registers.xml" debug_target_connection="J-Link" + gcc_enable_all_warnings="Yes" gcc_entry_point="Reset_Handler" link_use_linker_script_file="No" linker_memory_map_file="$(ProjectDir)/ATSAMD21G18A_MemoryMap.xml" diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index 61d92b602..e88c2ac6d 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -67,13 +67,12 @@ typedef struct uint8_t* buffer ; ///< buffer pointer uint16_t depth ; ///< max items uint16_t item_size ; ///< size of each item + bool overwritable ; volatile uint16_t count ; ///< number of items in queue volatile uint16_t wr_idx ; ///< write pointer volatile uint16_t rd_idx ; ///< read pointer - bool overwritable ; - #if CFG_FIFO_MUTEX tu_fifo_mutex_t mutex; #endif diff --git a/src/device/usbd.c b/src/device/usbd.c index ddb63cebb..206b663c0 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -161,8 +161,9 @@ enum { USBD_CLASS_DRIVER_COUNT = sizeof(usbd_class_drivers) / sizeof(usbd_class_ //--------------------------------------------------------------------+ OSAL_TASK_DEF(_usbd_task_def, "usbd", usbd_task, CFG_TUD_TASK_PRIO, CFG_TUD_TASK_STACK_SZ); -/*------------- event queue -------------*/ -OSAL_QUEUE_DEF(_usbd_qdef, CFG_TUD_TASK_QUEUE_SZ, dcd_event_t); +// Event queue +// role device/host is used by OS NONE for mutex (disable usb isr) only +OSAL_QUEUE_DEF(OPT_MODE_DEVICE, _usbd_qdef, CFG_TUD_TASK_QUEUE_SZ, dcd_event_t); static osal_queue_t _usbd_q; //--------------------------------------------------------------------+ @@ -200,15 +201,8 @@ tusb_error_t usbd_init (void) for (uint8_t i = 0; i < USBD_CLASS_DRIVER_COUNT; i++) usbd_class_drivers[i].init(); // Init device controller driver - #if (CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE) - dcd_init(0); - dcd_int_enable(0); - #endif - - #if (CFG_TUSB_RHPORT1_MODE & OPT_MODE_DEVICE) - dcd_init(1); - dcd_int_enable(1); - #endif + dcd_init(TUD_OPT_RHPORT); + dcd_int_enable(TUD_OPT_RHPORT); return TUSB_ERROR_NONE; } @@ -268,14 +262,14 @@ static void usbd_task_body(void) break; case DCD_EVENT_BUS_RESET: - // note: if task is too slow, we could clear the event of the new attached usbd_reset(event.rhport); + // TODO remove since if task is too slow, we could clear the event of the new attached osal_queue_reset(_usbd_q); break; case DCD_EVENT_UNPLUGGED: - // note: if task is too slow, we could clear the event of the new attached usbd_reset(event.rhport); + // TODO remove since if task is too slow, we could clear the event of the new attached osal_queue_reset(_usbd_q); tud_umount_cb(); // invoke callback @@ -587,6 +581,11 @@ void dcd_event_handler(dcd_event_t const * event, bool in_isr) TU_ASSERT(event->xfer_complete.result == XFER_RESULT_SUCCESS,); break; + // Not an DCD event, just a convenient way to defer ISR function should we need + case USBD_EVT_FUNC_CALL: + osal_queue_send(_usbd_q, event, in_isr); + break; + default: break; } } @@ -622,6 +621,8 @@ void dcd_event_xfer_complete (uint8_t rhport, uint8_t ep_addr, uint32_t xferred_ //--------------------------------------------------------------------+ // Helper //--------------------------------------------------------------------+ + +// Helper to parse an pair of endpoint descriptors (IN & OUT) tusb_error_t usbd_open_edpt_pair(uint8_t rhport, tusb_desc_endpoint_t const* p_desc_ep, uint8_t xfer_type, uint8_t* ep_out, uint8_t* ep_in) { for(int i=0; i<2; i++) @@ -645,7 +646,8 @@ tusb_error_t usbd_open_edpt_pair(uint8_t rhport, tusb_desc_endpoint_t const* p_d return TUSB_ERROR_NONE; } -void usbd_defer_func(osal_task_func_t func, void* param, bool in_isr ) +// Helper to defer an isr function +void usbd_defer_func(osal_task_func_t func, void* param, bool in_isr) { dcd_event_t event = { @@ -656,7 +658,7 @@ void usbd_defer_func(osal_task_func_t func, void* param, bool in_isr ) event.func_call.func = func; event.func_call.param = param; - osal_queue_send(_usbd_q, &event, in_isr); + dcd_event_handler(&event, in_isr); } #endif diff --git a/src/osal/osal_freertos.h b/src/osal/osal_freertos.h index 52cadd798..704aafd64 100644 --- a/src/osal/osal_freertos.h +++ b/src/osal/osal_freertos.h @@ -139,7 +139,9 @@ static inline bool osal_mutex_unlock(osal_mutex_t mutex_hdl) //--------------------------------------------------------------------+ // QUEUE API //--------------------------------------------------------------------+ -#define OSAL_QUEUE_DEF(_name, _depth, _type) \ + +// role device/host is used by OS NONE for mutex (disable usb isr) only +#define OSAL_QUEUE_DEF(_role, _name, _depth, _type) \ static _type _name##_##buf[_depth];\ osal_queue_def_t _name = { .depth = _depth, .item_sz = sizeof(_type), .buf = _name##_##buf }; diff --git a/src/osal/osal_mynewt.h b/src/osal/osal_mynewt.h index cb09680e0..62b5b45e8 100644 --- a/src/osal/osal_mynewt.h +++ b/src/osal/osal_mynewt.h @@ -75,7 +75,9 @@ static inline void osal_task_delay(uint32_t msec) //--------------------------------------------------------------------+ // QUEUE API //--------------------------------------------------------------------+ -#define OSAL_QUEUE_DEF(_name, _depth, _type) \ + +// role device/host is used by OS NONE for mutex (disable usb isr) only +#define OSAL_QUEUE_DEF(_role, _name, _depth, _type) \ static _type _name##_##buf[_depth];\ static struct os_event* _name##_##evbuf[_depth];\ osal_queue_def_t _name = { .depth = _depth, .item_sz = sizeof(_type), .buf = _name##_##buf, .evbuf = _name##_##evbuf};\ diff --git a/src/osal/osal_none.h b/src/osal/osal_none.h index 40ecb9c37..115c50bdb 100644 --- a/src/osal/osal_none.h +++ b/src/osal/osal_none.h @@ -93,12 +93,11 @@ static inline void osal_semaphore_reset(osal_semaphore_t sem_hdl) static inline tusb_error_t osal_semaphore_wait(osal_semaphore_t sem_hdl, uint32_t msec) { (void) msec; while (true) { - while (sem_hdl->count == 0) { - } - if (sem_hdl->count == 0) { - sem_hdl->count--; - break; - } + while (sem_hdl->count == 0) { } + if (sem_hdl->count == 0) { + sem_hdl->count--; + break; + } } return TUSB_ERROR_NONE; } @@ -124,40 +123,90 @@ static inline osal_mutex_t osal_mutex_create(osal_mutex_def_t* mdef) //--------------------------------------------------------------------+ #include "common/tusb_fifo.h" -#define OSAL_QUEUE_DEF(_name, _depth, _type) TU_FIFO_DEF(_name, _depth, _type, false) +typedef struct +{ + uint8_t role; // device or host + tu_fifo_t ff; +}osal_queue_def_t; + +typedef osal_queue_def_t* osal_queue_t; + +// role device/host is used by OS NONE for mutex (disable usb isr) only +#define OSAL_QUEUE_DEF(_role, _name, _depth, _type) \ + uint8_t _name##_buf[_depth*sizeof(_type)]; \ + osal_queue_def_t _name = { \ + .role = _role, \ + .ff = { \ + .buffer = _name##_buf, \ + .depth = _depth, \ + .item_size = sizeof(_type), \ + .overwritable = false, \ + }\ + } + +// lock queue by disable usb isr +static inline void _osal_q_lock(osal_queue_t qhdl) +{ +#if TUSB_OPT_DEVICE_ENABLED + extern void dcd_int_disable(uint8_t rhport); + if (qhdl->role == OPT_MODE_DEVICE) dcd_int_disable(TUD_OPT_RHPORT); +#endif -typedef tu_fifo_t osal_queue_def_t; -typedef tu_fifo_t* osal_queue_t; +#if MODE_HOST_SUPPORTED + extern void hcd_int_disable(uint8_t rhport); + if (qhdl->role == OPT_MODE_HOST) hcd_int_disable(TUH_OPT_RHPORT); +#endif +} + +// unlock queue +static inline void _osal_q_unlock(osal_queue_t qhdl) +{ +#if TUSB_OPT_DEVICE_ENABLED + extern void dcd_int_enable(uint8_t rhport); + if (qhdl->role == OPT_MODE_DEVICE) dcd_int_enable(TUD_OPT_RHPORT); +#endif + +#if MODE_HOST_SUPPORTED + extern void hcd_int_enable(uint8_t rhport); + if (qhdl->role == OPT_MODE_HOST) hcd_int_enable(TUH_OPT_RHPORT); +#endif +} static inline osal_queue_t osal_queue_create(osal_queue_def_t* qdef) { - tu_fifo_clear(qdef); + tu_fifo_clear(&qdef->ff); return (osal_queue_t) qdef; } -static inline bool osal_queue_send(osal_queue_t const queue_hdl, void const * data, bool in_isr) +static inline bool osal_queue_send(osal_queue_t const qhdl, void const * data, bool in_isr) { if (!in_isr) { - tusb_hal_int_disable_all(); + _osal_q_lock(qhdl); } - bool success = tu_fifo_write( (tu_fifo_t*) queue_hdl, data); + + bool success = tu_fifo_write(&qhdl->ff, data); + if (!in_isr) { - tusb_hal_int_enable_all(); + _osal_q_unlock(qhdl); } + return success; } -static inline void osal_queue_reset(osal_queue_t const queue_hdl) +static inline void osal_queue_reset(osal_queue_t const qhdl) { // tusb_hal_int_disable_all(); - tu_fifo_clear( (tu_fifo_t*) queue_hdl); + tu_fifo_clear(&qhdl->ff); // tusb_hal_int_enable_all(); } -static inline bool osal_queue_receive(osal_queue_t const queue_hdl, void* data) { - tusb_hal_int_disable_all(); - bool success = tu_fifo_read(queue_hdl, data); - tusb_hal_int_enable_all(); +// non blocking +static inline bool osal_queue_receive(osal_queue_t const qhdl, void* data) +{ + _osal_q_lock(qhdl); + bool success = tu_fifo_read(&qhdl->ff, data); + _osal_q_unlock(qhdl); + return success; } diff --git a/src/tusb_hal.h b/src/tusb_hal.h index 301e8c2f2..804196ad2 100644 --- a/src/tusb_hal.h +++ b/src/tusb_hal.h @@ -55,38 +55,6 @@ extern "C" { // Only required to implement if using No RTOS (osal_none) uint32_t tusb_hal_millis(void); -// TODO remove -extern void dcd_int_enable (uint8_t rhport); -extern void dcd_int_disable(uint8_t rhport); - -// Enable all ports' interrupt -// TODO remove -static inline void tusb_hal_int_enable_all(void) -{ -#ifdef CFG_TUSB_RHPORT0_MODE - dcd_int_enable(0); -#endif - -#ifdef CFG_TUSB_RHPORT0_MODE - dcd_int_enable(1); -#endif -} - -// Disable all ports' interrupt -// TODO remove -static inline void tusb_hal_int_disable_all(void) -{ -#ifdef CFG_TUSB_RHPORT0_MODE - dcd_int_disable(0); -#endif - -#ifdef CFG_TUSB_RHPORT0_MODE - dcd_int_disable(1); -#endif -} - - - #ifdef __cplusplus } #endif diff --git a/src/tusb_option.h b/src/tusb_option.h index c558b30ff..6b84db21c 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -123,7 +123,6 @@ // Which roothub port is configured as device #define TUD_OPT_RHPORT ( (CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE) ? 0 : ((CFG_TUSB_RHPORT1_MODE & OPT_MODE_DEVICE) ? 1 : -1) ) - #if TUD_OPT_RHPORT == 0 #define TUD_OPT_HIGH_SPEED ( CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED ) #else -- cgit v1.3.1 From 9478c647e37f041694bc9057d16b0d66386a7c11 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 7 Dec 2018 12:23:37 +0700 Subject: change usbh_control_xfer name and signature --- src/common/tusb_types.h | 1 + src/host/hub.c | 77 +++++++++++++++------ src/host/usbh.c | 96 ++++++++++++++++----------- src/host/usbh.h | 4 +- tests/lpc18xx_43xx/test/host/usbh/test_usbh.c | 4 +- 5 files changed, 120 insertions(+), 62 deletions(-) (limited to 'src/common') diff --git a/src/common/tusb_types.h b/src/common/tusb_types.h index b11481b18..6ba713084 100644 --- a/src/common/tusb_types.h +++ b/src/common/tusb_types.h @@ -358,6 +358,7 @@ typedef struct ATTR_PACKED{ uint8_t type : 2; ///< Request type tusb_request_type_t. uint8_t direction : 1; ///< Direction type. tusb_dir_t } bmRequestType_bit; + uint8_t bmRequestType; }; diff --git a/src/host/hub.c b/src/host/hub.c index a418774f6..82ad2ba17 100644 --- a/src/host/hub.c +++ b/src/host/hub.c @@ -71,15 +71,27 @@ bool hub_port_clear_feature_subtask(uint8_t hub_addr, uint8_t hub_port, uint8_t { TU_ASSERT(HUB_FEATURE_PORT_CONNECTION_CHANGE <= feature && feature <= HUB_FEATURE_PORT_RESET_CHANGE); + tusb_control_request_t request = { + .bmRequestType_bit = { .recipient = TUSB_REQ_RCPT_OTHER, .type = TUSB_REQ_TYPE_CLASS, .direction = TUSB_DIR_OUT }, + .bRequest = HUB_REQUEST_CLEAR_FEATURE, + .wValue = feature, + .wIndex = hub_port, + .wLength = 0 + }; + //------------- Clear Port Feature request -------------// - TU_ASSERT( usbh_control_xfer_subtask( hub_addr, bm_request_type(TUSB_DIR_OUT, TUSB_REQ_TYPE_CLASS, TUSB_REQ_RCPT_OTHER), - HUB_REQUEST_CLEAR_FEATURE, feature, hub_port, - 0, NULL ) ); + TU_ASSERT( usbh_control_xfer( hub_addr, &request, NULL ) ); //------------- Get Port Status to check if feature is cleared -------------// - TU_ASSERT( usbh_control_xfer_subtask( hub_addr, bm_request_type(TUSB_DIR_IN, TUSB_REQ_TYPE_CLASS, TUSB_REQ_RCPT_OTHER), - HUB_REQUEST_GET_STATUS, 0, hub_port, - 4, hub_enum_buffer ) ); + request = (tusb_control_request_t ) { + .bmRequestType_bit = { .recipient = TUSB_REQ_RCPT_OTHER, .type = TUSB_REQ_TYPE_CLASS, .direction = TUSB_DIR_IN }, + .bRequest = HUB_REQUEST_GET_STATUS, + .wValue = 0, + .wIndex = hub_port, + .wLength = 4 + }; + + TU_ASSERT( usbh_control_xfer( hub_addr, &request, hub_enum_buffer ) ); //------------- Check if feature is cleared -------------// hub_port_status_response_t * p_port_status; @@ -96,16 +108,28 @@ bool hub_port_reset_subtask(uint8_t hub_addr, uint8_t hub_port) tusb_error_t error; //------------- Set Port Reset -------------// - TU_ASSERT( usbh_control_xfer_subtask( hub_addr, bm_request_type(TUSB_DIR_OUT, TUSB_REQ_TYPE_CLASS, TUSB_REQ_RCPT_OTHER), - HUB_REQUEST_SET_FEATURE, HUB_FEATURE_PORT_RESET, hub_port, - 0, NULL ) ); + tusb_control_request_t request = { + .bmRequestType_bit = { .recipient = TUSB_REQ_RCPT_OTHER, .type = TUSB_REQ_TYPE_CLASS, .direction = TUSB_DIR_OUT }, + .bRequest = HUB_REQUEST_SET_FEATURE, + .wValue = HUB_FEATURE_PORT_RESET, + .wIndex = hub_port, + .wLength = 0 + }; + + TU_ASSERT( usbh_control_xfer( hub_addr, &request, NULL ) ); osal_task_delay(RESET_DELAY); // TODO Hub wait for Status Endpoint on Reset Change //------------- Get Port Status to check if port is enabled, powered and reset_change -------------// - TU_ASSERT( usbh_control_xfer_subtask( hub_addr, bm_request_type(TUSB_DIR_IN, TUSB_REQ_TYPE_CLASS, TUSB_REQ_RCPT_OTHER), - HUB_REQUEST_GET_STATUS, 0, hub_port, - 4, hub_enum_buffer ) ); + request = (tusb_control_request_t ) { + .bmRequestType_bit = { .recipient = TUSB_REQ_RCPT_OTHER, .type = TUSB_REQ_TYPE_CLASS, .direction = TUSB_DIR_IN }, + .bRequest = HUB_REQUEST_GET_STATUS, + .wValue = 0, + .wIndex = hub_port, + .wLength = 4 + }; + + TU_ASSERT( usbh_control_xfer( hub_addr, &request, hub_enum_buffer ) ); hub_port_status_response_t * p_port_status; p_port_status = (hub_port_status_response_t *) hub_enum_buffer; @@ -152,20 +176,33 @@ bool hub_open_subtask(uint8_t dev_addr, tusb_desc_interface_t const *p_interface (*p_length) = sizeof(tusb_desc_interface_t) + sizeof(tusb_desc_endpoint_t); //------------- Get Hub Descriptor -------------// - TU_ASSERT( usbh_control_xfer_subtask( dev_addr, bm_request_type(TUSB_DIR_IN, TUSB_REQ_TYPE_CLASS, TUSB_REQ_RCPT_DEVICE), - HUB_REQUEST_GET_DESCRIPTOR, 0, 0, - sizeof(descriptor_hub_desc_t), hub_enum_buffer ) ); + tusb_control_request_t request = { + .bmRequestType_bit = { .recipient = TUSB_REQ_RCPT_DEVICE, .type = TUSB_REQ_TYPE_CLASS, .direction = TUSB_DIR_IN }, + .bRequest = HUB_REQUEST_GET_DESCRIPTOR, + .wValue = 0, + .wIndex = 0, + .wLength = sizeof(descriptor_hub_desc_t) + }; + + TU_ASSERT( usbh_control_xfer( dev_addr, &request, hub_enum_buffer ) ); // only care about this field in hub descriptor hub_data[dev_addr-1].port_number = ((descriptor_hub_desc_t*) hub_enum_buffer)->bNbrPorts; //------------- Set Port_Power on all ports -------------// - static uint8_t i; - for(i=1; i <= hub_data[dev_addr-1].port_number; i++) + // TODO may only power port with attached + request = (tusb_control_request_t ) { + .bmRequestType_bit = { .recipient = TUSB_REQ_RCPT_OTHER, .type = TUSB_REQ_TYPE_CLASS, .direction = TUSB_DIR_OUT }, + .bRequest = HUB_REQUEST_SET_FEATURE, + .wValue = HUB_FEATURE_PORT_POWER, + .wIndex = 0, + .wLength = 0 + }; + + for(uint8_t i=1; i <= hub_data[dev_addr-1].port_number; i++) { - TU_ASSERT( usbh_control_xfer_subtask( dev_addr, bm_request_type(TUSB_DIR_OUT, TUSB_REQ_TYPE_CLASS, TUSB_REQ_RCPT_OTHER), - HUB_REQUEST_SET_FEATURE, HUB_FEATURE_PORT_POWER, i, - 0, NULL ) ); + request.wIndex = i; + TU_ASSERT( usbh_control_xfer( dev_addr, &request, NULL ) ); } //------------- Queue the initial Status endpoint transfer -------------// diff --git a/src/host/usbh.c b/src/host/usbh.c index e96f5f669..ad0653cf4 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -190,20 +190,13 @@ bool usbh_init(void) } //------------- USBH control transfer -------------// -bool usbh_control_xfer_subtask (uint8_t dev_addr, uint8_t bmRequestType, uint8_t bRequest, - uint16_t wValue, uint16_t wIndex, uint16_t wLength, uint8_t* data) +bool usbh_control_xfer (uint8_t dev_addr, tusb_control_request_t* request, uint8_t* data) { usbh_device_t* dev = &_usbh_devices[dev_addr]; TU_ASSERT(osal_mutex_lock(dev->control.mutex_hdl, OSAL_TIMEOUT_NORMAL)); - dev->control.request = (tusb_control_request_t ) { - {.bmRequestType = bmRequestType}, - .bRequest = bRequest, - .wValue = wValue, - .wIndex = wIndex, - .wLength = wLength - }; + dev->control.request = *request; dev->control.pipe_status = 0; TU_ASSERT_ERR(hcd_pipe_control_xfer(dev_addr, &dev->control.request, data), false); @@ -383,6 +376,7 @@ bool enum_task(hcd_event_t* event) static uint8_t *p_desc = NULL; // TODO move usbh_device_t* dev0 = &_usbh_devices[0]; + tusb_control_request_t request; dev0->core_id = event->rhport; // TODO refractor integrate to device_pool dev0->hub_addr = event->plug.hub_addr; @@ -417,10 +411,15 @@ bool enum_task(hcd_event_t* event) else { //------------- Get Port Status -------------// - TU_VERIFY_HDLR( usbh_control_xfer_subtask( dev0->hub_addr, bm_request_type(TUSB_DIR_IN, TUSB_REQ_TYPE_CLASS, TUSB_REQ_RCPT_OTHER), - HUB_REQUEST_GET_STATUS, 0, dev0->hub_port, - 4, _usbh_ctrl_buf ) - , hub_status_pipe_queue( dev0->hub_addr) ); // TODO hub refractor + request = (tusb_control_request_t ) { + .bmRequestType_bit = { .recipient = TUSB_REQ_RCPT_OTHER, .type = TUSB_REQ_TYPE_CLASS, .direction = TUSB_DIR_IN }, + .bRequest = HUB_REQUEST_GET_STATUS, + .wValue = 0, + .wIndex = dev0->hub_port, + .wLength = 4 + }; + // TODO hub refractor + TU_VERIFY_HDLR( usbh_control_xfer( dev0->hub_addr, &request, _usbh_ctrl_buf ), hub_status_pipe_queue( dev0->hub_addr) ); // Acknowledge Port Connection Change hub_port_clear_feature_subtask(dev0->hub_addr, dev0->hub_port, HUB_FEATURE_PORT_CONNECTION_CHANGE); @@ -456,9 +455,14 @@ bool enum_task(hcd_event_t* event) dev0->state = TUSB_DEVICE_STATE_ADDRESSED; //------------- Get first 8 bytes of device descriptor to get Control Endpoint Size -------------// - bool is_ok = usbh_control_xfer_subtask(0, bm_request_type(TUSB_DIR_IN, TUSB_REQ_TYPE_STANDARD, TUSB_REQ_RCPT_DEVICE), - TUSB_REQ_GET_DESCRIPTOR, - (TUSB_DESC_DEVICE << 8), 0, 8, _usbh_ctrl_buf); + request = (tusb_control_request_t ) { + .bmRequestType_bit = { .recipient = TUSB_REQ_RCPT_DEVICE, .type = TUSB_REQ_TYPE_STANDARD, .direction = TUSB_DIR_IN }, + .bRequest = TUSB_REQ_GET_DESCRIPTOR, + .wValue = TUSB_DESC_DEVICE << 8, + .wIndex = 0, + .wLength = 8 + }; + bool is_ok = usbh_control_xfer(0, &request, _usbh_ctrl_buf); //------------- Reset device again before Set Address -------------// if (dev0->hub_addr == 0) @@ -488,9 +492,14 @@ bool enum_task(hcd_event_t* event) uint8_t const new_addr = get_new_address(); TU_ASSERT(new_addr <= CFG_TUSB_HOST_DEVICE_MAX); // TODO notify application we reach max devices - TU_ASSERT(usbh_control_xfer_subtask( 0, bm_request_type(TUSB_DIR_OUT, TUSB_REQ_TYPE_STANDARD, TUSB_REQ_RCPT_DEVICE), - TUSB_REQ_SET_ADDRESS, new_addr, 0, - 0, NULL )); + request = (tusb_control_request_t ) { + .bmRequestType_bit = { .recipient = TUSB_REQ_RCPT_DEVICE, .type = TUSB_REQ_TYPE_STANDARD, .direction = TUSB_DIR_OUT }, + .bRequest = TUSB_REQ_SET_ADDRESS, + .wValue = new_addr, + .wIndex = 0, + .wLength = 0 + }; + TU_ASSERT(usbh_control_xfer(0, &request, NULL)); //------------- update port info & close control pipe of addr0 -------------// usbh_device_t* new_dev = &_usbh_devices[new_addr]; @@ -507,11 +516,14 @@ bool enum_task(hcd_event_t* event) TU_ASSERT_ERR ( usbh_pipe_control_open(new_addr, ((tusb_desc_device_t*) _usbh_ctrl_buf)->bMaxPacketSize0 ) ); //------------- Get full device descriptor -------------// - TU_ASSERT( - usbh_control_xfer_subtask(new_addr, bm_request_type(TUSB_DIR_IN, TUSB_REQ_TYPE_STANDARD, TUSB_REQ_RCPT_DEVICE), - TUSB_REQ_GET_DESCRIPTOR, (TUSB_DESC_DEVICE << 8), 0, - 18, - _usbh_ctrl_buf)); + request = (tusb_control_request_t ) { + .bmRequestType_bit = { .recipient = TUSB_REQ_RCPT_DEVICE, .type = TUSB_REQ_TYPE_STANDARD, .direction = TUSB_DIR_IN }, + .bRequest = TUSB_REQ_GET_DESCRIPTOR, + .wValue = TUSB_DESC_DEVICE << 8, + .wIndex = 0, + .wLength = 18 + }; + TU_ASSERT(usbh_control_xfer(new_addr, &request, _usbh_ctrl_buf)); // update device info TODO alignment issue new_dev->vendor_id = ((tusb_desc_device_t*) _usbh_ctrl_buf)->idVendor; @@ -522,28 +534,34 @@ bool enum_task(hcd_event_t* event) TU_ASSERT(configure_selected <= new_dev->configure_count); // TODO notify application when invalid configuration //------------- Get 9 bytes of configuration descriptor -------------// - TU_ASSERT( - usbh_control_xfer_subtask(new_addr, bm_request_type(TUSB_DIR_IN, TUSB_REQ_TYPE_STANDARD, TUSB_REQ_RCPT_DEVICE), - TUSB_REQ_GET_DESCRIPTOR, - (TUSB_DESC_CONFIGURATION << 8) | (configure_selected - 1), 0, - 9, - _usbh_ctrl_buf)); + request = (tusb_control_request_t ) { + .bmRequestType_bit = { .recipient = TUSB_REQ_RCPT_DEVICE, .type = TUSB_REQ_TYPE_STANDARD, .direction = TUSB_DIR_IN }, + .bRequest = TUSB_REQ_GET_DESCRIPTOR, + .wValue = (TUSB_DESC_CONFIGURATION << 8) | (configure_selected - 1), + .wIndex = 0, + .wLength = 9 + }; + TU_ASSERT( usbh_control_xfer(new_addr, &request, _usbh_ctrl_buf)); - TU_VERIFY_HDLR( CFG_TUSB_HOST_ENUM_BUFFER_SIZE >= ((tusb_desc_configuration_t*)_usbh_ctrl_buf)->wTotalLength, - tuh_device_mount_failed_cb(TUSB_ERROR_USBH_MOUNT_CONFIG_DESC_TOO_LONG, NULL) ); + // TODO not enough buffer to hold configuration descriptor + TU_ASSERT( CFG_TUSB_HOST_ENUM_BUFFER_SIZE >= ((tusb_desc_configuration_t*)_usbh_ctrl_buf)->wTotalLength ); //------------- Get full configuration descriptor -------------// - TU_ASSERT( usbh_control_xfer_subtask( new_addr, bm_request_type(TUSB_DIR_IN, TUSB_REQ_TYPE_STANDARD, TUSB_REQ_RCPT_DEVICE), - TUSB_REQ_GET_DESCRIPTOR, (TUSB_DESC_CONFIGURATION << 8) | (configure_selected - 1), 0, - CFG_TUSB_HOST_ENUM_BUFFER_SIZE, _usbh_ctrl_buf ) ); + request.wLength = ((tusb_desc_configuration_t*)_usbh_ctrl_buf)->wTotalLength; // full length + TU_ASSERT( usbh_control_xfer( new_addr, &request, _usbh_ctrl_buf ) ); // update configuration info new_dev->interface_count = ((tusb_desc_configuration_t*) _usbh_ctrl_buf)->bNumInterfaces; //------------- Set Configure -------------// - TU_ASSERT( usbh_control_xfer_subtask( new_addr, bm_request_type(TUSB_DIR_OUT, TUSB_REQ_TYPE_STANDARD, TUSB_REQ_RCPT_DEVICE), - TUSB_REQ_SET_CONFIGURATION, configure_selected, 0, - 0, NULL )); + request = (tusb_control_request_t ) { + .bmRequestType_bit = { .recipient = TUSB_REQ_RCPT_DEVICE, .type = TUSB_REQ_TYPE_STANDARD, .direction = TUSB_DIR_OUT }, + .bRequest = TUSB_REQ_SET_CONFIGURATION, + .wValue = configure_selected, + .wIndex = 0, + .wLength = 0 + }; + TU_ASSERT(usbh_control_xfer( new_addr, &request, NULL )); new_dev->state = TUSB_DEVICE_STATE_CONFIGURED; @@ -607,6 +625,8 @@ bool usbh_task_body(void) case HCD_EVENT_DEVICE_UNPLUG: enum_task(&event); break; + + default: break; } } } diff --git a/src/host/usbh.h b/src/host/usbh.h index bcbf2902c..039997a24 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -100,8 +100,8 @@ ATTR_WEAK void tuh_device_mount_failed_cb(tusb_error_t error, tusb_desc_devic bool usbh_init(void); void usbh_task(void* param); -bool usbh_control_xfer_subtask(uint8_t dev_addr, uint8_t bmRequestType, uint8_t bRequest, - uint16_t wValue, uint16_t wIndex, uint16_t wLength, uint8_t* data); +bool usbh_control_xfer (uint8_t dev_addr, tusb_control_request_t* request, uint8_t* data); + #endif #ifdef __cplusplus diff --git a/tests/lpc18xx_43xx/test/host/usbh/test_usbh.c b/tests/lpc18xx_43xx/test/host/usbh/test_usbh.c index 75da7cfdf..dde629cf0 100644 --- a/tests/lpc18xx_43xx/test/host/usbh/test_usbh.c +++ b/tests/lpc18xx_43xx/test/host/usbh/test_usbh.c @@ -222,7 +222,7 @@ void test_usbh_control_xfer_mutex_failed(void) osal_mutex_release_ExpectAndReturn(_usbh_devices[dev_addr].control.mutex_hdl, TUSB_ERROR_NONE); //------------- Code Under Test -------------// - usbh_control_xfer_subtask(dev_addr, 1, 2, 3, 4, 0, NULL); + usbh_control_xfer(dev_addr, 1, 2, 3, 4, 0, NULL); } void test_usbh_control_xfer_ok(void) @@ -244,7 +244,7 @@ void test_usbh_control_xfer_ok(void) osal_mutex_release_ExpectAndReturn(_usbh_devices[dev_addr].control.mutex_hdl, TUSB_ERROR_NONE); //------------- Code Under Test -------------// - usbh_control_xfer_subtask(dev_addr, 1, 2, 3, 4, 0, NULL); + usbh_control_xfer(dev_addr, 1, 2, 3, 4, 0, NULL); } //void test_usbh_xfer_isr_non_control_stalled(void) // do nothing for stall on control -- cgit v1.3.1 From 9c4c7975024e9b971a43a866c1feffb419dd8f5b Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 10 Dec 2018 19:01:28 +0700 Subject: add ep addr to host cdc --- src/class/cdc/cdc_device.c | 7 +- src/class/cdc/cdc_host.c | 83 +++++++++++++-------- src/class/cdc/cdc_host.h | 12 +-- src/common/tusb_common.h | 61 ++++----------- src/device/usbd.c | 16 ++-- src/host/ehci/ehci.c | 86 +++++----------------- src/host/ehci/ehci.h | 8 +- .../test/host/ehci/test_ehci_structure.c | 2 +- 8 files changed, 104 insertions(+), 171 deletions(-) (limited to 'src/common') diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index 040c8d4f4..d477a0d23 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -41,9 +41,7 @@ #if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_CDC) #define _TINY_USB_SOURCE_FILE_ -//--------------------------------------------------------------------+ -// INCLUDE -//--------------------------------------------------------------------+ + #include "cdc_device.h" #include "device/usbd_pvt.h" @@ -236,8 +234,7 @@ tusb_error_t cdcd_open(uint8_t rhport, tusb_desc_interface_t const * p_interface if ( CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL != p_interface_desc->bInterfaceSubClass) return TUSB_ERROR_CDC_UNSUPPORTED_SUBCLASS; // Only support AT commands, no protocol and vendor specific commands. - if ( !(tu_within(CDC_COMM_PROTOCOL_ATCOMMAND, p_interface_desc->bInterfaceProtocol, CDC_COMM_PROTOCOL_ATCOMMAND_CDMA) || - p_interface_desc->bInterfaceProtocol == CDC_COMM_PROTOCOL_NONE || + if ( !(tu_within(CDC_COMM_PROTOCOL_NONE, p_interface_desc->bInterfaceProtocol, CDC_COMM_PROTOCOL_ATCOMMAND_CDMA) || p_interface_desc->bInterfaceProtocol == 0xff ) ) { return TUSB_ERROR_CDC_UNSUPPORTED_PROTOCOL; diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index 290cbfb44..0d0378920 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -42,24 +42,35 @@ #define _TINY_USB_SOURCE_FILE_ -//--------------------------------------------------------------------+ -// INCLUDE -//--------------------------------------------------------------------+ #include "common/tusb_common.h" #include "cdc_host.h" //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ +typedef struct { + uint8_t itf_num; + uint8_t itf_protocol; + + cdc_acm_capability_t acm_capability; + + pipe_handle_t pipe_notification, pipe_out, pipe_in; + + uint8_t ep_notif; + uint8_t ep_in; + uint8_t ep_out; + +} cdch_data_t; //--------------------------------------------------------------------+ // INTERNAL OBJECT & FUNCTION DECLARATION //--------------------------------------------------------------------+ -static cdch_data_t cdch_data[CFG_TUSB_HOST_DEVICE_MAX]; // TODO to be static +static cdch_data_t cdch_data[CFG_TUSB_HOST_DEVICE_MAX]; -static inline bool tuh_cdc_mounted(uint8_t dev_addr) +bool tuh_cdc_mounted(uint8_t dev_addr) { - return pipehandle_is_valid(cdch_data[dev_addr-1].pipe_in) && pipehandle_is_valid(cdch_data[dev_addr-1].pipe_out); + cdch_data_t* cdc = &cdch_data[dev_addr-1]; + return cdc->ep_in && cdc->ep_out; } bool tuh_cdc_is_busy(uint8_t dev_addr, cdc_pipeid_t pipeid) @@ -91,8 +102,8 @@ bool tuh_cdc_serial_is_mounted(uint8_t dev_addr) { // TODO consider all AT Command as serial candidate return tuh_cdc_mounted(dev_addr) && - (CDC_COMM_PROTOCOL_ATCOMMAND <= cdch_data[dev_addr-1].interface_protocol) && - (cdch_data[dev_addr-1].interface_protocol <= CDC_COMM_PROTOCOL_ATCOMMAND_CDMA); + (CDC_COMM_PROTOCOL_ATCOMMAND <= cdch_data[dev_addr-1].itf_protocol) && + (cdch_data[dev_addr-1].itf_protocol <= CDC_COMM_PROTOCOL_ATCOMMAND_CDMA); } tusb_error_t tuh_cdc_send(uint8_t dev_addr, void const * p_data, uint32_t length, bool is_notify) @@ -125,33 +136,33 @@ void cdch_init(void) tu_memclr(cdch_data, sizeof(cdch_data_t)*CFG_TUSB_HOST_DEVICE_MAX); } -bool cdch_open_subtask(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *p_interface_desc, uint16_t *p_length) +bool cdch_open_subtask(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t *p_length) { - // TODO change following assert to subtask_assert - if ( CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL != p_interface_desc->bInterfaceSubClass) return TUSB_ERROR_CDC_UNSUPPORTED_SUBCLASS; + // Only support ACM + TU_VERIFY( CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL == itf_desc->bInterfaceSubClass); - if ( !(tu_within(CDC_COMM_PROTOCOL_ATCOMMAND, p_interface_desc->bInterfaceProtocol, CDC_COMM_PROTOCOL_ATCOMMAND_CDMA) || - 0xff == p_interface_desc->bInterfaceProtocol) ) - { - return TUSB_ERROR_CDC_UNSUPPORTED_PROTOCOL; - } + // Only support AT commands, no protocol and vendor specific commands. + TU_VERIFY(tu_within(CDC_COMM_PROTOCOL_NONE, itf_desc->bInterfaceProtocol, CDC_COMM_PROTOCOL_ATCOMMAND_CDMA) || + 0xff == itf_desc->bInterfaceProtocol); uint8_t const * p_desc; cdch_data_t * p_cdc; - p_desc = descriptor_next ( (uint8_t const *) p_interface_desc ); - p_cdc = &cdch_data[dev_addr-1]; // non-static variable cannot be used after OS service call + p_desc = descriptor_next ( (uint8_t const *) itf_desc ); + p_cdc = &cdch_data[dev_addr-1]; - p_cdc->interface_number = p_interface_desc->bInterfaceNumber; - p_cdc->interface_protocol = p_interface_desc->bInterfaceProtocol; // TODO 0xff is consider as rndis candidate, other is virtual Com + p_cdc->itf_num = itf_desc->bInterfaceNumber; + p_cdc->itf_protocol = itf_desc->bInterfaceProtocol; // TODO 0xff is consider as rndis candidate, other is virtual Com //------------- Communication Interface -------------// (*p_length) = sizeof(tusb_desc_interface_t); + // Communication Functional Descriptors while( TUSB_DESC_CLASS_SPECIFIC == p_desc[DESC_OFFSET_TYPE] ) - { // Communication Functional Descriptors + { if ( CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT == cdc_functional_desc_typeof(p_desc) ) - { // save ACM bmCapabilities + { + // save ACM bmCapabilities p_cdc->acm_capability = ((cdc_desc_func_acm_t const *) p_desc)->bmCapabilities; } @@ -160,8 +171,12 @@ bool cdch_open_subtask(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t c } if ( TUSB_DESC_ENDPOINT == p_desc[DESC_OFFSET_TYPE]) - { // notification endpoint if any - p_cdc->pipe_notification = hcd_pipe_open(rhport, dev_addr, (tusb_desc_endpoint_t const *) p_desc, TUSB_CLASS_CDC); + { + // notification endpoint if any + tusb_desc_endpoint_t const * ep_desc = (tusb_desc_endpoint_t const *) p_desc; + p_cdc->pipe_notification = hcd_pipe_open(rhport, dev_addr, ep_desc, TUSB_CLASS_CDC); + + p_cdc->ep_notif = ep_desc->bEndpointAddress; (*p_length) += p_desc[DESC_OFFSET_LEN]; p_desc = descriptor_next(p_desc); @@ -179,16 +194,24 @@ bool cdch_open_subtask(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t c // data endpoints expected to be in pairs for(uint32_t i=0; i<2; i++) { - tusb_desc_endpoint_t const *p_endpoint = (tusb_desc_endpoint_t const *) p_desc; - TU_ASSERT(TUSB_DESC_ENDPOINT == p_endpoint->bDescriptorType); - TU_ASSERT(TUSB_XFER_BULK == p_endpoint->bmAttributes.xfer); + tusb_desc_endpoint_t const *ep_desc = (tusb_desc_endpoint_t const *) p_desc; + TU_ASSERT(TUSB_DESC_ENDPOINT == ep_desc->bDescriptorType); + TU_ASSERT(TUSB_XFER_BULK == ep_desc->bmAttributes.xfer); - pipe_handle_t * p_pipe_hdl = ( p_endpoint->bEndpointAddress & TUSB_DIR_IN_MASK ) ? + pipe_handle_t * p_pipe_hdl = ( ep_desc->bEndpointAddress & TUSB_DIR_IN_MASK ) ? &p_cdc->pipe_in : &p_cdc->pipe_out; - (*p_pipe_hdl) = hcd_pipe_open(rhport, dev_addr, p_endpoint, TUSB_CLASS_CDC); + (*p_pipe_hdl) = hcd_pipe_open(rhport, dev_addr, ep_desc, TUSB_CLASS_CDC); TU_ASSERT ( pipehandle_is_valid(*p_pipe_hdl) ); + if ( edpt_dir(ep_desc->bEndpointAddress) == TUSB_DIR_IN ) + { + p_cdc->ep_in = ep_desc->bEndpointAddress; + }else + { + p_cdc->ep_out = ep_desc->bEndpointAddress; + } + (*p_length) += p_desc[DESC_OFFSET_LEN]; p_desc = descriptor_next( p_desc ); } @@ -203,7 +226,7 @@ bool cdch_open_subtask(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t c .bmRequestType_bit = { .recipient = TUSB_REQ_RCPT_INTERFACE, .type = TUSB_REQ_TYPE_CLASS, .direction = TUSB_DIR_OUT }, .bRequest = CDC_REQUEST_SET_CONTROL_LINE_STATE, .wValue = 0x03, // dtr on, cst on - .wIndex = p_cdc->interface_number, + .wIndex = p_cdc->itf_num, .wLength = 0 }; diff --git a/src/class/cdc/cdc_host.h b/src/class/cdc/cdc_host.h index 2fbd40f40..eceec3ee3 100644 --- a/src/class/cdc/cdc_host.h +++ b/src/class/cdc/cdc_host.h @@ -137,18 +137,8 @@ void tuh_cdc_xfer_isr(uint8_t dev_addr, xfer_result_t event, cdc_pipeid_t pipe_i //--------------------------------------------------------------------+ #ifdef _TINY_USB_SOURCE_FILE_ -typedef struct { - uint8_t interface_number; - uint8_t interface_protocol; - - cdc_acm_capability_t acm_capability; - - pipe_handle_t pipe_notification, pipe_out, pipe_in; - -} cdch_data_t; - void cdch_init(void); -bool cdch_open_subtask(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *p_interface_desc, uint16_t *p_length) ATTR_WARN_UNUSED_RESULT; +bool cdch_open_subtask(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *p_interface_desc, uint16_t *p_length); void cdch_isr(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); void cdch_close(uint8_t dev_addr); diff --git a/src/common/tusb_common.h b/src/common/tusb_common.h index 3c5402e59..f4fac96b8 100644 --- a/src/common/tusb_common.h +++ b/src/common/tusb_common.h @@ -73,6 +73,8 @@ // MACROS //--------------------------------------------------------------------+ #define TU_ARRAY_SZIE(_arr) ( sizeof(_arr) / sizeof(_arr[0]) ) +#define TU_MIN(_x, _y) ( (_x) < (_y) ) ? (_x) : (_y) ) +#define TU_MAX(_x, _y) ( (_x) > (_y) ) ? (_x) : (_y) ) #define U16_HIGH_U8(u16) ((uint8_t) (((u16) >> 8) & 0x00ff)) #define U16_LOW_U8(u16) ((uint8_t) ((u16) & 0x00ff)) @@ -167,53 +169,23 @@ static inline uint16_t tu_u16_le2be(uint16_t u16) return ((uint16_t)(tu_u16_low(u16) << 8)) | tu_u16_high(u16); } -//------------- Min -------------// -static inline uint8_t tu_min8(uint8_t x, uint8_t y) -{ - return (x < y) ? x : y; -} - -static inline uint16_t tu_min16(uint16_t x, uint16_t y) -{ - return (x < y) ? x : y; -} - -static inline uint32_t tu_min32(uint32_t x, uint32_t y) -{ - return (x < y) ? x : y; -} - -//------------- Max -------------// -static inline uint32_t tu_max32(uint32_t x, uint32_t y) -{ - return (x > y) ? x : y; -} - -//------------- Align -------------// -static inline uint32_t tu_align32 (uint32_t value) -{ - return (value & 0xFFFFFFE0UL); -} - -static inline uint32_t tu_align16 (uint32_t value) -{ - return (value & 0xFFFFFFF0UL); -} +// Min +static inline uint8_t tu_min8(uint8_t x, uint8_t y) { return (x < y) ? x : y; } +static inline uint16_t tu_min16(uint16_t x, uint16_t y) { return (x < y) ? x : y; } +static inline uint32_t tu_min32(uint32_t x, uint32_t y) { return (x < y) ? x : y; } -static inline uint32_t tu_align_n (uint32_t alignment, uint32_t value) -{ - return value & ((uint32_t) ~(alignment-1)); -} +// Max +static inline uint8_t tu_max8(uint8_t x, uint8_t y) { return (x > y) ? x : y; } +static inline uint16_t tu_max16(uint16_t x, uint16_t y) { return (x > y) ? x : y; } +static inline uint32_t tu_max32(uint32_t x, uint32_t y) { return (x > y) ? x : y; } -static inline uint32_t tu_align4k (uint32_t value) -{ - return (value & 0xFFFFF000UL); -} +// Align +static inline uint32_t tu_align32 (uint32_t value) { return (value & 0xFFFFFFE0UL); } +static inline uint32_t tu_align16 (uint32_t value) { return (value & 0xFFFFFFF0UL); } +static inline uint32_t tu_align_n (uint32_t alignment, uint32_t value) { return value & ((uint32_t) ~(alignment-1)); } +static inline uint32_t tu_align4k (uint32_t value) { return (value & 0xFFFFF000UL); } -static inline uint32_t tu_offset4k(uint32_t value) -{ - return (value & 0xFFFUL); -} +static inline uint32_t tu_offset4k(uint32_t value) { return (value & 0xFFFUL); } //------------- Mathematics -------------// static inline uint32_t tu_abs(int32_t value) @@ -221,7 +193,6 @@ static inline uint32_t tu_abs(int32_t value) return (value < 0) ? (-value) : value; } - /// inclusive range checking static inline bool tu_within(uint32_t lower, uint32_t value, uint32_t upper) { diff --git a/src/device/usbd.c b/src/device/usbd.c index 5262d6c73..d1b708a0d 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -623,24 +623,24 @@ void dcd_event_xfer_complete (uint8_t rhport, uint8_t ep_addr, uint32_t xferred_ //--------------------------------------------------------------------+ // Helper to parse an pair of endpoint descriptors (IN & OUT) -tusb_error_t usbd_open_edpt_pair(uint8_t rhport, tusb_desc_endpoint_t const* p_desc_ep, uint8_t xfer_type, uint8_t* ep_out, uint8_t* ep_in) +tusb_error_t usbd_open_edpt_pair(uint8_t rhport, tusb_desc_endpoint_t const* ep_desc, uint8_t xfer_type, uint8_t* ep_out, uint8_t* ep_in) { for(int i=0; i<2; i++) { - TU_ASSERT(TUSB_DESC_ENDPOINT == p_desc_ep->bDescriptorType && - xfer_type == p_desc_ep->bmAttributes.xfer, TUSB_ERROR_DESCRIPTOR_CORRUPTED); + TU_ASSERT(TUSB_DESC_ENDPOINT == ep_desc->bDescriptorType && + xfer_type == ep_desc->bmAttributes.xfer, TUSB_ERROR_DESCRIPTOR_CORRUPTED); - TU_ASSERT( dcd_edpt_open(rhport, p_desc_ep), TUSB_ERROR_DCD_OPEN_PIPE_FAILED ); + TU_ASSERT( dcd_edpt_open(rhport, ep_desc), TUSB_ERROR_DCD_OPEN_PIPE_FAILED ); - if ( edpt_dir(p_desc_ep->bEndpointAddress) == TUSB_DIR_IN ) + if ( edpt_dir(ep_desc->bEndpointAddress) == TUSB_DIR_IN ) { - (*ep_in) = p_desc_ep->bEndpointAddress; + (*ep_in) = ep_desc->bEndpointAddress; }else { - (*ep_out) = p_desc_ep->bEndpointAddress; + (*ep_out) = ep_desc->bEndpointAddress; } - p_desc_ep = (tusb_desc_endpoint_t const *) descriptor_next( (uint8_t const*) p_desc_ep ); + ep_desc = (tusb_desc_endpoint_t const *) descriptor_next( (uint8_t const*) ep_desc ); } return TUSB_ERROR_NONE; diff --git a/src/host/ehci/ehci.c b/src/host/ehci/ehci.c index 4989c74a0..2e9090db2 100644 --- a/src/host/ehci/ehci.c +++ b/src/host/ehci/ehci.c @@ -58,26 +58,8 @@ //--------------------------------------------------------------------+ // INTERNAL OBJECT & FUNCTION DECLARATION //--------------------------------------------------------------------+ -CFG_TUSB_MEM_SECTION static ehci_data_t ehci_data; - -#if EHCI_PERIODIC_LIST - - #if (CFG_TUSB_RHPORT0_MODE & OPT_MODE_HOST) - CFG_TUSB_MEM_SECTION ATTR_ALIGNED(4096) static ehci_link_t period_frame_list0[EHCI_FRAMELIST_SIZE]; - - #ifndef __ICCARM__ // IAR cannot able to determine the alignment with datalignment pragma - TU_VERIFY_STATIC( ALIGN_OF(period_frame_list0) == 4096, "Period Framelist must be 4k alginment"); // validation - #endif - #endif - - #if (CFG_TUSB_RHPORT1_MODE & OPT_MODE_HOST) - CFG_TUSB_MEM_SECTION ATTR_ALIGNED(4096) STATIC_VAR ehci_link_t period_frame_list1[EHCI_FRAMELIST_SIZE]; - - #ifndef __ICCARM__ // IAR cannot able to determine the alignment with datalignment pragma - TU_VERIFY_STATIC( ALIGN_OF(period_frame_list1) == 4096, "Period Framelist must be 4k alginment"); // validation - #endif - #endif -#endif +// Periodic frame list must be 4K alignment +CFG_TUSB_MEM_SECTION ATTR_ALIGNED(4096) static ehci_data_t ehci_data; //------------- Validation -------------// // TODO static assert for memory placement on some known MCU such as lpc43xx @@ -86,7 +68,6 @@ CFG_TUSB_MEM_SECTION static ehci_data_t ehci_data; // PROTOTYPE //--------------------------------------------------------------------+ static inline ehci_registers_t* get_operational_register(uint8_t hostid) ATTR_PURE ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT; -static inline ehci_link_t* get_period_frame_list(uint8_t hostid) ATTR_PURE ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT; static inline ehci_qhd_t* get_async_head(uint8_t hostid) ATTR_ALWAYS_INLINE ATTR_PURE ATTR_WARN_UNUSED_RESULT; static inline ehci_link_t* get_period_head(uint8_t hostid, uint8_t interval_ms) ATTR_ALWAYS_INLINE ATTR_PURE ATTR_WARN_UNUSED_RESULT; @@ -112,9 +93,9 @@ static void qhd_init(ehci_qhd_t *p_qhd, uint8_t dev_addr, tusb_desc_endpoint_t c static inline ehci_qtd_t* qtd_find_free(uint8_t dev_addr) ATTR_PURE ATTR_ALWAYS_INLINE; -static inline ehci_qtd_t* qtd_next(ehci_qtd_t const * p_qtd ) ATTR_PURE ATTR_ALWAYS_INLINE; -static inline void qtd_insert_to_qhd(ehci_qhd_t *p_qhd, ehci_qtd_t *p_qtd_new) ATTR_ALWAYS_INLINE; -static inline void qtd_remove_1st_from_qhd(ehci_qhd_t *p_qhd) ATTR_ALWAYS_INLINE; +static inline ehci_qtd_t* qtd_next(ehci_qtd_t const * p_qtd ) ATTR_PURE ATTR_ALWAYS_INLINE; +static inline void qtd_insert_to_qhd(ehci_qhd_t *p_qhd, ehci_qtd_t *p_qtd_new) ATTR_ALWAYS_INLINE; +static inline void qtd_remove_1st_from_qhd(ehci_qhd_t *p_qhd) ATTR_ALWAYS_INLINE; static void qtd_init(ehci_qtd_t* p_qtd, uint32_t data_ptr, uint16_t total_bytes); static inline void list_insert(ehci_link_t *current, ehci_link_t *new, uint8_t new_type) ATTR_ALWAYS_INLINE; @@ -129,18 +110,8 @@ static bool ehci_init(uint8_t hostid); //--------------------------------------------------------------------+ bool hcd_init(void) { - //------------- Data Structure init -------------// tu_memclr(&ehci_data, sizeof(ehci_data_t)); - - #if (CFG_TUSB_RHPORT0_MODE & OPT_MODE_HOST) - TU_VERIFY(ehci_init(0)); - #endif - - #if (CFG_TUSB_RHPORT1_MODE & OPT_MODE_HOST) - TU_VERIFY(ehci_init(1)); - #endif - - return true; + return ehci_init(TUH_OPT_RHPORT); } //--------------------------------------------------------------------+ @@ -148,7 +119,7 @@ bool hcd_init(void) //--------------------------------------------------------------------+ void hcd_port_reset(uint8_t hostid) { - ehci_registers_t* const regs = get_operational_register(hostid); + ehci_registers_t* regs = ehci_data.regs; regs->portsc_bit.port_enable = 0; // disable port before reset regs->portsc_bit.port_reset = 1; @@ -156,19 +127,18 @@ void hcd_port_reset(uint8_t hostid) bool hcd_port_connect_status(uint8_t hostid) { - return get_operational_register(hostid)->portsc_bit.current_connect_status; + return ehci_data.regs->portsc_bit.current_connect_status; } tusb_speed_t hcd_port_speed_get(uint8_t hostid) { - return (tusb_speed_t) get_operational_register(hostid)->portsc_bit.nxp_port_speed; // NXP specific port speed + return (tusb_speed_t) ehci_data.regs->portsc_bit.nxp_port_speed; // NXP specific port speed } // TODO refractor abtract later void hcd_port_unplug(uint8_t hostid) { - ehci_registers_t* const regs = get_operational_register(hostid); - regs->usb_cmd_bit.advacne_async = 1; // Async doorbell check EHCI 4.8.2 for operational details + ehci_data.regs->usb_cmd_bit.advance_async = 1; // Async doorbell check EHCI 4.8.2 for operational details } //--------------------------------------------------------------------+ @@ -176,7 +146,9 @@ void hcd_port_unplug(uint8_t hostid) //--------------------------------------------------------------------+ static bool ehci_init(uint8_t hostid) { - ehci_registers_t* const regs = get_operational_register(hostid); + ehci_data.regs = get_operational_register(hostid); + + ehci_registers_t* regs = ehci_data.regs; //------------- CTRLDSSEGMENT Register (skip) -------------// //------------- USB INT Register -------------// @@ -211,7 +183,7 @@ static bool ehci_init(uint8_t hostid) ehci_data.period_head_arr[i].qtd_overlay.halted = 1; // dummy node, always inactive } - ehci_link_t * const framelist = get_period_frame_list(hostid); + ehci_link_t * const framelist = ehci_data.period_framelist; ehci_link_t * const period_1ms = get_period_head(hostid, 1); // all links --> period_head_arr[0] (1ms) // 0, 2, 4, 6 etc --> period_head_arr[1] (2ms) @@ -264,11 +236,11 @@ static bool ehci_init(uint8_t hostid) static tusb_error_t hcd_controller_stop(uint8_t hostid) { - ehci_registers_t* const regs = get_operational_register(hostid); - tu_timeout_t timeout; + ehci_registers_t* regs = ehci_data.regs; regs->usb_cmd_bit.run_stop = 0; + tu_timeout_t timeout; tu_timeout_set(&timeout, 2); // USB Spec: controller has to stop within 16 uframe = 2 frames while( regs->usb_sts_bit.hc_halted == 0 && !tu_timeout_expired(&timeout)) {} @@ -613,10 +585,8 @@ static void async_advance_isr(ehci_qhd_t * const async_head) static void port_connect_status_change_isr(uint8_t hostid) { - ehci_registers_t* const regs = get_operational_register(hostid); - // NOTE There is an sequence plug->unplug->…..-> plug if device is powering with pre-plugged device - if (regs->portsc_bit.current_connect_status) + if (ehci_data.regs->portsc_bit.current_connect_status) { hcd_port_reset(hostid); hcd_event_device_attach(hostid); @@ -797,7 +767,7 @@ static void xfer_error_isr(uint8_t hostid) //------------- Host Controller Driver's Interrupt Handler -------------// void hal_hcd_isr(uint8_t hostid) { - ehci_registers_t* const regs = get_operational_register(hostid); + ehci_registers_t* regs = ehci_data.regs; uint32_t int_status = regs->usb_sts; int_status &= regs->usb_int_enable; @@ -854,26 +824,6 @@ static inline ehci_registers_t* get_operational_register(uint8_t hostid) return (ehci_registers_t*) (hostid ? (&LPC_USB1->USBCMD_H) : (&LPC_USB0->USBCMD_H) ); } -#if EHCI_PERIODIC_LIST // TODO refractor/group this together -static inline ehci_link_t* get_period_frame_list(uint8_t hostid) -{ - switch(hostid) - { -#if (CFG_TUSB_RHPORT0_MODE & OPT_MODE_HOST) - case 0: - return period_frame_list0; -#endif - -#if (CFG_TUSB_RHPORT1_MODE & OPT_MODE_HOST) - case 1: - return period_frame_list1; -#endif - - default: return NULL; - } -} -#endif - //------------- queue head helper -------------// static inline ehci_qhd_t* get_async_head(uint8_t hostid) { diff --git a/src/host/ehci/ehci.h b/src/host/ehci/ehci.h index 48e0c34e5..4534c4cd3 100644 --- a/src/host/ehci/ehci.h +++ b/src/host/ehci/ehci.h @@ -352,7 +352,7 @@ typedef volatile struct { uint32_t framelist_size : 2 ; ///< This field is R/W only if Programmable Frame List Flagin the HCCPARAMS registers is set to a one. This field specifies the size of the frame list.00b 1024 elements (4096 bytes) Default value 01b 512 elements (2048 bytes) 10b 256 elements (1024 bytes) uint32_t periodic_enable : 1 ; ///< This bit controls whether the host controller skips processing the Periodic Schedule. Values mean: 0b Do not process the Periodic Schedule 1b Use the PERIODICLISTBASE register to access the Periodic Schedule. uint32_t async_enable : 1 ; ///< This bit controls whether the host controller skips processing the Asynchronous Schedule. Values mean: 0b Do not process the Asynchronous Schedule 1b Use the ASYNCLISTADDR register to access the Asynchronous Schedule. - uint32_t advacne_async : 1 ; ///< This bit is used as a doorbell by software to tell the host controller to issue an interrupt the next time it advances asynchronous schedule. Software must write a 1 to this bit to ringthe doorbell. When the host controller has evicted all appropriate cached schedule state, it sets the Interrupt on Async Advancestatus bit in the USBSTS register. If the Interrupt on Async Advance Enablebit in the USBINTR register is a one then the host controller will assert an interrupt at the next interrupt threshold. See Section 4.8.2 for operational details. The host controller sets this bit to a zero after it has set the Interrupt on Async Advance status bit in the USBSTS register to a one. Software should not write a one to this bit when the asynchronous schedule is disabled. Doing so will yield undefined results. + uint32_t advance_async : 1 ; ///< This bit is used as a doorbell by software to tell the host controller to issue an interrupt the next time it advances asynchronous schedule. Software must write a 1 to this bit to ringthe doorbell. When the host controller has evicted all appropriate cached schedule state, it sets the Interrupt on Async Advancestatus bit in the USBSTS register. If the Interrupt on Async Advance Enablebit in the USBINTR register is a one then the host controller will assert an interrupt at the next interrupt threshold. See Section 4.8.2 for operational details. The host controller sets this bit to a zero after it has set the Interrupt on Async Advance status bit in the USBSTS register to a one. Software should not write a one to this bit when the asynchronous schedule is disabled. Doing so will yield undefined results. uint32_t light_reset : 1 ; ///< This control bit is not required. If implemented, it allows the driver to reset the EHCI controller without affecting the state of the ports or the relationship to the companion host controllers. For example, the PORSTC registers should not be reset to their default values and the CF bit setting should not go to zero (retaining port ownership relationships). A host software read of this bit as zero indicates the Light Host Controller Reset has completed and it is safe for host software to re-initialize the host controller. A host software read of this bit as a one indicates the Light Host Controller Reset has not yet completed. uint32_t async_park : 2 ; ///< It contains a count of the number of successive transactions the host controller is allowed to execute from a high-speed queue head on the Asynchronous schedule before continuing traversal of the Asynchronous schedule. See Section 4.10.3.2 for full operational details. Valid values are 1h to 3h. Software must not write a zero to this bit when Park Mode Enableis a one as this will result in undefined behavior. uint32_t : 1 ; ///< reserved @@ -450,11 +450,11 @@ typedef volatile struct { //--------------------------------------------------------------------+ typedef struct { -#if EHCI_PERIODIC_LIST + ehci_link_t period_framelist[EHCI_FRAMELIST_SIZE]; + // for NXP ECHI, only implement 1 ms & 2 ms & 4 ms, 8 ms (framelist) // [0] : 1ms, [1] : 2ms, [2] : 4ms, [3] : 8 ms ehci_qhd_t period_head_arr[4]; -#endif struct { ehci_qhd_t qhd; // also used as head of async list (each for 1 controller), always exists @@ -472,6 +472,8 @@ typedef struct // ehci_itd_t itd[EHCI_MAX_ITD] ; ///< Iso Transfer Pool // ehci_sitd_t sitd[EHCI_MAX_SITD] ; ///< Split (FS) Isochronous Transfer Pool }device[CFG_TUSB_HOST_DEVICE_MAX]; + + ehci_registers_t* regs; }ehci_data_t; #ifdef __cplusplus diff --git a/tests/lpc18xx_43xx/test/host/ehci/test_ehci_structure.c b/tests/lpc18xx_43xx/test/host/ehci/test_ehci_structure.c index 7eaabcd51..39e15b227 100644 --- a/tests/lpc18xx_43xx/test/host/ehci/test_ehci_structure.c +++ b/tests/lpc18xx_43xx/test/host/ehci/test_ehci_structure.c @@ -225,7 +225,7 @@ void test_register_usbcmd(void) TEST_ASSERT_EQUAL( 2 , BITFIELD_OFFSET_OF_MEMBER(ehci_registers_t, usb_cmd_bit, framelist_size) ); TEST_ASSERT_EQUAL( 4 , BITFIELD_OFFSET_OF_MEMBER(ehci_registers_t, usb_cmd_bit, periodic_enable) ); TEST_ASSERT_EQUAL( 5 , BITFIELD_OFFSET_OF_MEMBER(ehci_registers_t, usb_cmd_bit, async_enable) ); - TEST_ASSERT_EQUAL( 6 , BITFIELD_OFFSET_OF_MEMBER(ehci_registers_t, usb_cmd_bit, advacne_async) ); + TEST_ASSERT_EQUAL( 6 , BITFIELD_OFFSET_OF_MEMBER(ehci_registers_t, usb_cmd_bit, advance_async) ); TEST_ASSERT_EQUAL( 7 , BITFIELD_OFFSET_OF_MEMBER(ehci_registers_t, usb_cmd_bit, light_reset) ); TEST_ASSERT_EQUAL( 8 , BITFIELD_OFFSET_OF_MEMBER(ehci_registers_t, usb_cmd_bit, async_park) ); TEST_ASSERT_EQUAL( 11 , BITFIELD_OFFSET_OF_MEMBER(ehci_registers_t, usb_cmd_bit, async_park_enable) ); -- cgit v1.3.1 From 600fac1845abec7630adda4dc7487f7711a58300 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 11 Dec 2018 16:18:56 +0700 Subject: fix build error with ohci --- src/class/cdc/cdc_host.c | 1 + src/common/tusb_types.h | 4 +- src/host/ohci/ohci.c | 245 +++++++++++++++++------------------------------ src/host/ohci/ohci.h | 28 +++--- src/host/usbh.c | 2 +- 5 files changed, 101 insertions(+), 179 deletions(-) (limited to 'src/common') diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index df07e0683..53f62d684 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -226,6 +226,7 @@ bool cdch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *it void cdch_isr(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) { + (void) ep_addr; tuh_cdc_xfer_isr( dev_addr, event, 0, xferred_bytes ); } diff --git a/src/common/tusb_types.h b/src/common/tusb_types.h index 6ba713084..8be1e87f6 100644 --- a/src/common/tusb_types.h +++ b/src/common/tusb_types.h @@ -392,9 +392,9 @@ static inline uint8_t edpt_number(uint8_t addr) return addr & (~TUSB_DIR_IN_MASK); } -static inline uint8_t edpt_addr(uint8_t num, tusb_dir_t dir) +static inline uint8_t edpt_addr(uint8_t num, uint8_t dir) { - return num | (dir == TUSB_DIR_IN ? TUSB_DIR_IN_MASK : 0); + return num | (dir ? TUSB_DIR_IN_MASK : 0); } //--------------------------------------------------------------------+ diff --git a/src/host/ohci/ohci.c b/src/host/ohci/ohci.c index 4c54c5eaa..5593cd55d 100644 --- a/src/host/ohci/ohci.c +++ b/src/host/ohci/ohci.c @@ -136,7 +136,7 @@ enum { //--------------------------------------------------------------------+ // INTERNAL OBJECT & FUNCTION DECLARATION //--------------------------------------------------------------------+ -CFG_TUSB_MEM_SECTION ATTR_ALIGNED(256) STATIC_VAR ohci_data_t ohci_data; +CFG_TUSB_MEM_SECTION ATTR_ALIGNED(256) static ohci_data_t ohci_data; static ohci_ed_t * const p_ed_head[] = { @@ -216,11 +216,11 @@ tusb_speed_t hcd_port_speed_get(uint8_t hostid) return OHCI_REG->rhport_status_bit[0].low_speed_device_attached ? TUSB_SPEED_LOW : TUSB_SPEED_FULL; } -// TODO refractor abtract later -void hcd_port_unplug(uint8_t hostid) +void hcd_device_remove(uint8_t rhport, uint8_t dev_addr) { // TODO OHCI - (void) hostid; + (void) rhport; + (void) dev_addr; } //--------------------------------------------------------------------+ @@ -273,67 +273,6 @@ static void gtd_init(ohci_gtd_t* p_td, void* data_ptr, uint16_t total_bytes) p_td->buffer_end = total_bytes ? (((uint8_t*) data_ptr) + total_bytes-1) : NULL; } - -bool hcd_pipe_control_open(uint8_t dev_addr, uint8_t max_packet_size) -{ - ohci_ed_t* p_ed = &ohci_data.control[dev_addr].ed; - - ed_init(p_ed, dev_addr, max_packet_size, 0, TUSB_XFER_CONTROL, 0); // TODO binterval of control is ignored - - if ( dev_addr != 0 ) - { // insert to control head - ed_list_insert( p_ed_head[TUSB_XFER_CONTROL], p_ed); - }else - { - p_ed->skip = 0; // addr0 is used as static control head --> only need to clear skip bit - } - - return true; -} - -//bool hcd_pipe_control_xfer(uint8_t dev_addr, tusb_control_request_t const * p_request, uint8_t data[]) -//{ -// ohci_ed_t* const p_ed = &ohci_data.control[dev_addr].ed; -// -// ohci_gtd_t *p_setup = &ohci_data.control[dev_addr].gtd[0]; -// ohci_gtd_t *p_data = p_setup + 1; -// ohci_gtd_t *p_status = p_setup + 2; -// -// //------------- SETUP Phase -------------// -// gtd_init(p_setup, (void*) p_request, 8); -// p_setup->index = dev_addr; -// p_setup->pid = OHCI_PID_SETUP; -// p_setup->data_toggle = BIN8(10); // DATA0 -// p_setup->next_td = (uint32_t) p_data; -// -// //------------- DATA Phase -------------// -// if (p_request->wLength > 0) -// { -// gtd_init(p_data, data, p_request->wLength); -// p_data->index = dev_addr; -// p_data->pid = p_request->bmRequestType_bit.direction ? OHCI_PID_IN : OHCI_PID_OUT; -// p_data->data_toggle = BIN8(11); // DATA1 -// }else -// { -// p_data = p_setup; -// } -// p_data->next_td = (uint32_t) p_status; -// -// //------------- STATUS Phase -------------// -// gtd_init(p_status, NULL, 0); // zero-length data -// p_status->index = dev_addr; -// p_status->pid = p_request->bmRequestType_bit.direction ? OHCI_PID_OUT : OHCI_PID_IN; // reverse direction of data phase -// p_status->data_toggle = BIN8(11); // DATA1 -// p_status->delay_interrupt = OHCI_INT_ON_COMPLETE_YES; -// -// //------------- Attach TDs list to Control Endpoint -------------// -// p_ed->td_head.address = (uint32_t) p_setup; -// -// OHCI_REG->command_status_bit.control_list_filled = 1; -// -// return true; -//} - bool hcd_pipe_control_close(uint8_t dev_addr) { ohci_ed_t* const p_ed = &ohci_data.control[dev_addr].ed; @@ -352,13 +291,6 @@ bool hcd_pipe_control_close(uint8_t dev_addr) return true; } -bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const* ep_desc) -{ - // FIXME control only for now - (void) rhport; - return hcd_pipe_control_open(dev_addr, ep_desc->wMaxPacketSize.size); -} - bool hcd_edpt_close(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) { // FIXME control only for now @@ -373,7 +305,7 @@ bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet (void) rhport; ohci_ed_t* p_ed = &ohci_data.control[dev_addr].ed; - ohci_gtd_t *p_setup = &ohci_data.control[dev_addr].gtd[0]; + ohci_gtd_t *p_setup = &ohci_data.control[dev_addr].gtd; gtd_init(p_setup, (void*) setup_packet, 8); p_setup->index = dev_addr; @@ -400,7 +332,7 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * if ( epnum == 0 ) { ohci_ed_t* const p_ed = &ohci_data.control[dev_addr].ed; - ohci_gtd_t *p_data = &ohci_data.control[dev_addr].gtd[0]; + ohci_gtd_t *p_data = &ohci_data.control[dev_addr].gtd; gtd_init(p_data, buffer, buflen); @@ -420,27 +352,31 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * //--------------------------------------------------------------------+ // BULK/INT/ISO PIPE API //--------------------------------------------------------------------+ -static inline uint8_t ed_get_index(ohci_ed_t const * const p_ed) ATTR_PURE ATTR_ALWAYS_INLINE; -static inline uint8_t ed_get_index(ohci_ed_t const * const p_ed) +static inline ohci_ed_t * ed_from_addr(uint8_t dev_addr, uint8_t ep_addr) { - return p_ed - ohci_data.device[p_ed->device_address-1].ed; -} + if ( edpt_number(ep_addr) == 0 ) return &ohci_data.control[dev_addr].ed; -static inline ohci_ed_t * ed_from_pipe_handle(pipe_handle_t pipe_hdl) ATTR_PURE ATTR_ALWAYS_INLINE; -static inline ohci_ed_t * ed_from_pipe_handle(pipe_handle_t pipe_hdl) -{ - return &ohci_data.device[pipe_hdl.dev_addr-1].ed[pipe_hdl.index]; + ohci_ed_t* ed_pool = ohci_data.ed_pool; + + for(uint32_t i=0; iused = 0; // free ED } -pipe_handle_t hcd_edpt_open(uint8_t dev_addr, tusb_desc_endpoint_t const * p_endpoint_desc, uint8_t class_code) +bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc) { - pipe_handle_t const null_handle = { .dev_addr = 0, .xfer_type = 0, .index = 0 }; + (void) rhport; // TODO iso support - TU_ASSERT(p_endpoint_desc->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS, null_handle ); + TU_ASSERT(ep_desc->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS); //------------- Prepare Queue Head -------------// - ohci_ed_t * const p_ed = ed_find_free(dev_addr); - TU_ASSERT(p_ed, null_handle); + ohci_ed_t * p_ed; - ed_init( p_ed, dev_addr, p_endpoint_desc->wMaxPacketSize.size, p_endpoint_desc->bEndpointAddress, - p_endpoint_desc->bmAttributes.xfer, p_endpoint_desc->bInterval ); - p_ed->td_tail.class_code = class_code; + if ( ep_desc->bEndpointAddress == 0 ) + { + p_ed = &ohci_data.control[dev_addr].ed; + }else + { + p_ed = ed_find_free(); + } + TU_ASSERT(p_ed); - ed_list_insert( p_ed_head[p_endpoint_desc->bmAttributes.xfer], p_ed ); + ed_init( p_ed, dev_addr, ep_desc->wMaxPacketSize.size, ep_desc->bEndpointAddress, + ep_desc->bmAttributes.xfer, ep_desc->bInterval ); - return (pipe_handle_t) + // control of dev0 is used as static async head + if ( dev_addr == 0 ) { - .dev_addr = dev_addr, - .xfer_type = p_endpoint_desc->bmAttributes.xfer, - .index = ed_get_index(p_ed) - }; + p_ed->skip = 0; // only need to clear skip bit + return true; + } + + ed_list_insert( p_ed_head[ep_desc->bmAttributes.xfer], p_ed ); + + return true; } -static ohci_gtd_t * gtd_find_free(uint8_t dev_addr) +static ohci_gtd_t * gtd_find_free(void) { for(uint8_t i=0; i < HCD_MAX_XFER; i++) { - if (!ohci_data.device[dev_addr-1].gtd[i].used) - { - return &ohci_data.device[dev_addr-1].gtd[i]; - } + if ( !ohci_data.gtd_pool[i].used ) return &ohci_data.gtd_pool[i]; } return NULL; @@ -532,72 +474,71 @@ static void td_insert_to_ed(ohci_ed_t* p_ed, ohci_gtd_t * p_gtd) } } -static tusb_error_t pipe_queue_xfer(pipe_handle_t pipe_hdl, uint8_t buffer[], uint16_t total_bytes, bool int_on_complete) +static bool pipe_queue_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t buffer[], uint16_t total_bytes, bool int_on_complete) { - ohci_ed_t* const p_ed = ed_from_pipe_handle(pipe_hdl); + ohci_ed_t* const p_ed = ed_from_addr(dev_addr, ep_addr); - if ( !p_ed->is_iso ) - { - ohci_gtd_t * const p_gtd = gtd_find_free(pipe_hdl.dev_addr); - TU_ASSERT(p_gtd, TUSB_ERROR_EHCI_NOT_ENOUGH_QTD); // TODO refractor error code + // not support ISO yet + TU_VERIFY ( !p_ed->is_iso ); - gtd_init(p_gtd, buffer, total_bytes); - p_gtd->index = pipe_hdl.index; - if ( int_on_complete ) p_gtd->delay_interrupt = OHCI_INT_ON_COMPLETE_YES; + ohci_gtd_t * const p_gtd = gtd_find_free(); + TU_ASSERT(p_gtd); // not enough gtd - td_insert_to_ed(p_ed, p_gtd); - }else - { - TU_ASSERT_ERR(TUSB_ERROR_NOT_SUPPORTED_YET); - } + gtd_init(p_gtd, buffer, total_bytes); + p_gtd->index = p_ed-ohci_data.ed_pool; + + if ( int_on_complete ) p_gtd->delay_interrupt = OHCI_INT_ON_COMPLETE_YES; + + td_insert_to_ed(p_ed, p_gtd); - return TUSB_ERROR_NONE; + return true; } -tusb_error_t hcd_pipe_queue_xfer(pipe_handle_t pipe_hdl, uint8_t buffer[], uint16_t total_bytes) +bool hcd_pipe_queue_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t buffer[], uint16_t total_bytes) { - return pipe_queue_xfer(pipe_hdl, buffer, total_bytes, false); + return pipe_queue_xfer(dev_addr, ep_addr, buffer, total_bytes, false); } -tusb_error_t hcd_pipe_xfer(pipe_handle_t pipe_hdl, uint8_t buffer[], uint16_t total_bytes, bool int_on_complete) +bool hcd_pipe_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t buffer[], uint16_t total_bytes, bool int_on_complete) { (void) int_on_complete; - TU_ASSERT_ERR( pipe_queue_xfer(pipe_hdl, buffer, total_bytes, true) ); + TU_ASSERT( pipe_queue_xfer(dev_addr, ep_addr, buffer, total_bytes, true) ); - tusb_xfer_type_t xfer_type = ed_get_xfer_type( ed_from_pipe_handle(pipe_hdl) ); + tusb_xfer_type_t xfer_type = ed_get_xfer_type( ed_from_addr(dev_addr, ep_addr) ); if (TUSB_XFER_BULK == xfer_type) OHCI_REG->command_status_bit.bulk_list_filled = 1; - return TUSB_ERROR_NONE; + return true; } /// pipe_close should only be called as a part of unmount/safe-remove process // endpoints are tied to an address, which only reclaim after a long delay when enumerating // thus there is no need to make sure ED is not in HC's cahed as it will not for sure -tusb_error_t hcd_pipe_close(pipe_handle_t pipe_hdl) +bool hcd_pipe_close(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) { - ohci_ed_t * const p_ed = ed_from_pipe_handle(pipe_hdl); + (void) rhport; + ohci_ed_t * const p_ed = ed_from_addr(dev_addr, ep_addr); ed_list_remove( p_ed_head[ ed_get_xfer_type(p_ed)], p_ed ); - return TUSB_ERROR_FAILED; + return true; } -bool hcd_edpt_busy(pipe_handle_t pipe_hdl) +bool hcd_edpt_busy(uint8_t dev_addr, uint8_t ep_addr) { - ohci_ed_t const * const p_ed = ed_from_pipe_handle(pipe_hdl); + ohci_ed_t const * const p_ed = ed_from_addr(dev_addr, ep_addr); return tu_align16(p_ed->td_head.address) != tu_align16(p_ed->td_tail.address); } -bool hcd_edpt_stalled(pipe_handle_t pipe_hdl) +bool hcd_edpt_stalled(uint8_t dev_addr, uint8_t ep_addr) { - ohci_ed_t const * const p_ed = ed_from_pipe_handle(pipe_hdl); + ohci_ed_t const * const p_ed = ed_from_addr(dev_addr, ep_addr); return p_ed->td_head.halted && p_ed->is_stalled; } -tusb_error_t hcd_edpt_clear_stall(pipe_handle_t pipe_hdl) +bool hcd_edpt_clear_stall(uint8_t dev_addr, uint8_t ep_addr) { - ohci_ed_t * const p_ed = ed_from_pipe_handle(pipe_hdl); + ohci_ed_t * const p_ed = ed_from_addr(dev_addr, ep_addr); p_ed->is_stalled = 0; p_ed->td_tail.address &= 0x0Ful; // set tail pointer back to NULL @@ -607,7 +548,7 @@ tusb_error_t hcd_edpt_clear_stall(pipe_handle_t pipe_hdl) if ( TUSB_XFER_BULK == ed_get_xfer_type(p_ed) ) OHCI_REG->command_status_bit.bulk_list_filled = 1; - return TUSB_ERROR_NONE; + return true; } @@ -632,13 +573,11 @@ static ohci_td_item_t* list_reverse(ohci_td_item_t* td_head) return td_reverse_head; } -static inline bool gtd_is_control(ohci_gtd_t const * const p_qtd) ATTR_CONST ATTR_ALWAYS_INLINE; static inline bool gtd_is_control(ohci_gtd_t const * const p_qtd) { - return ((uint32_t) p_qtd) < ((uint32_t) ohci_data.device); // check ohci_data_t for memory layout + return ((uint32_t) p_qtd) < ((uint32_t) ohci_data.gtd_pool); // check ohci_data_t for memory layout } -static inline ohci_ed_t* gtd_get_ed(ohci_gtd_t const * const p_qtd) ATTR_PURE ATTR_ALWAYS_INLINE; static inline ohci_ed_t* gtd_get_ed(ohci_gtd_t const * const p_qtd) { if ( gtd_is_control(p_qtd) ) @@ -646,13 +585,10 @@ static inline ohci_ed_t* gtd_get_ed(ohci_gtd_t const * const p_qtd) return &ohci_data.control[p_qtd->index].ed; }else { - uint8_t dev_addr_idx = (((uint32_t)p_qtd) - ((uint32_t)ohci_data.device)) / sizeof(ohci_data.device[0]); - - return &ohci_data.device[dev_addr_idx].ed[p_qtd->index]; + return &ohci_data.ed_pool[p_qtd->index]; } } -static inline uint32_t gtd_xfer_byte_left(uint32_t buffer_end, uint32_t current_buffer) ATTR_CONST ATTR_ALWAYS_INLINE; static inline uint32_t gtd_xfer_byte_left(uint32_t buffer_end, uint32_t current_buffer) { // 5.2.9 OHCI sample code return (tu_align4k(buffer_end ^ current_buffer) ? 0x1000 : 0) + @@ -663,18 +599,16 @@ static void done_queue_isr(uint8_t hostid) { (void) hostid; - uint8_t max_loop = (CFG_TUSB_HOST_DEVICE_MAX+1)*(HCD_MAX_XFER+OHCI_MAX_ITD); - // done head is written in reversed order of completion --> need to reverse the done queue first ohci_td_item_t* td_head = list_reverse ( (ohci_td_item_t*) tu_align16(ohci_data.hcca.done_head) ); - while( td_head != NULL && max_loop > 0) + while( td_head != NULL ) { // TODO check if td_head is iso td //------------- Non ISO transfer -------------// ohci_gtd_t * const p_qtd = (ohci_gtd_t *) td_head; xfer_result_t const event = (p_qtd->condition_code == OHCI_CCODE_NO_ERROR) ? XFER_RESULT_SUCCESS : - (p_qtd->condition_code == OHCI_CCODE_STALL) ? XFER_RESULT_STALLED : XFER_RESULT_FAILED; + (p_qtd->condition_code == OHCI_CCODE_STALL) ? XFER_RESULT_STALLED : XFER_RESULT_FAILED; p_qtd->used = 0; // free TD if ( (p_qtd->delay_interrupt == OHCI_INT_ON_COMPLETE_YES) || (event != XFER_RESULT_SUCCESS) ) @@ -697,19 +631,12 @@ static void done_queue_isr(uint8_t hostid) if ( event == XFER_RESULT_STALLED ) p_ed->is_stalled = 1; } - pipe_handle_t pipe_hdl = - { - .dev_addr = p_ed->device_address, - .xfer_type = ed_get_xfer_type(p_ed), - }; - - if ( pipe_hdl.xfer_type != TUSB_XFER_CONTROL) pipe_hdl.index = ed_get_index(p_ed); - - hcd_event_xfer_complete(pipe_hdl, p_ed->td_tail.class_code, event, xferred_bytes); + hcd_event_xfer_complete(p_ed->device_address, + edpt_addr(p_ed->endpoint_number, p_ed->direction == OHCI_PID_IN), + event, xferred_bytes); } td_head = (ohci_td_item_t*) td_head->next_td; - max_loop--; } } diff --git a/src/host/ohci/ohci.h b/src/host/ohci/ohci.h index c407b8ac1..f68500703 100644 --- a/src/host/ohci/ohci.h +++ b/src/host/ohci/ohci.h @@ -88,8 +88,9 @@ typedef struct { }ohci_td_item_t; -typedef struct ATTR_ALIGNED(16) { - //------------- Word 0 -------------// +typedef struct ATTR_ALIGNED(16) +{ + // Word 0 uint32_t used : 1; uint32_t index : 4; // endpoint index the td belongs to, or device address in case of control xfer uint32_t expected_bytes : 13; // TODO available for hcd @@ -100,15 +101,14 @@ typedef struct ATTR_ALIGNED(16) { volatile uint32_t data_toggle : 2; volatile uint32_t error_count : 2; volatile uint32_t condition_code : 4; - /*---------- End Word 1 ----------*/ - //------------- Word 1 -------------// + // Word 1 volatile uint8_t* current_buffer_pointer; - //------------- Word 2 -------------// + // Word 2 volatile uint32_t next_td; - //------------- Word 3 -------------// + // Word 3 uint8_t* buffer_end; } ohci_gtd_t; @@ -132,11 +132,7 @@ typedef struct ATTR_ALIGNED(16) { //------------- Word 1 -------------// union { - uint32_t address; // 4 lsb bits are free to use - struct { - uint32_t class_code : 4; // FIXME refractor to use interface number instead - uint32_t : 28; - }; + uint32_t address; }td_tail; //------------- Word 2 -------------// @@ -190,14 +186,12 @@ typedef struct ATTR_ALIGNED(256) { // control endpoints has reserved resources struct { ohci_ed_t ed; - ohci_gtd_t gtd[3]; // setup, data, status + ohci_gtd_t gtd; }control[CFG_TUSB_HOST_DEVICE_MAX+1]; - struct { - // ochi_itd_t itd[OHCI_MAX_ITD]; // itd requires alignment of 32 - ohci_ed_t ed[HCD_MAX_ENDPOINT]; - ohci_gtd_t gtd[HCD_MAX_XFER]; - }device[CFG_TUSB_HOST_DEVICE_MAX]; + // ochi_itd_t itd[OHCI_MAX_ITD]; // itd requires alignment of 32 + ohci_ed_t ed_pool[HCD_MAX_ENDPOINT]; + ohci_gtd_t gtd_pool[HCD_MAX_XFER]; } ohci_data_t; diff --git a/src/host/usbh.c b/src/host/usbh.c index ff4343fd2..456eff531 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -515,7 +515,7 @@ bool enum_task(hcd_event_t* event) new_dev->speed = dev0->speed; new_dev->state = TUSB_DEVICE_STATE_ADDRESSED; - usbh_pipe_control_close(0); + usbh_pipe_control_close(0); // hcd_device_remove(rhport, 0); // close device 0 dev0->state = TUSB_DEVICE_STATE_UNPLUG; // open control pipe for new address -- cgit v1.3.1 From 67d6d753d66ffb821e9cfc4831d44f6b2f8549b8 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 11 Dec 2018 23:57:53 +0700 Subject: replace all hcd pipe close by hcd_device_remove --- src/class/cdc/cdc_host.c | 5 -- src/class/hid/hid_host.c | 1 - src/class/msc/msc_host.c | 3 - src/common/tusb_types.h | 5 -- src/host/ehci/ehci.c | 223 +++++++++++++++++------------------------------ src/host/ehci/ehci.h | 8 +- src/host/hcd.h | 6 +- src/host/hub.c | 2 - src/host/usbh.c | 32 ++----- 9 files changed, 94 insertions(+), 191 deletions(-) (limited to 'src/common') diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index 53f62d684..159a13990 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -233,11 +233,6 @@ void cdch_isr(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t x void cdch_close(uint8_t dev_addr) { cdch_data_t * p_cdc = &cdch_data[dev_addr-1]; - - hcd_pipe_close(TUH_OPT_RHPORT, dev_addr, p_cdc->ep_notif); - hcd_pipe_close(TUH_OPT_RHPORT, dev_addr, p_cdc->ep_in); - hcd_pipe_close(TUH_OPT_RHPORT, dev_addr, p_cdc->ep_out); - tu_memclr(p_cdc, sizeof(cdch_data_t)); } diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index aa93f7837..1e44055ec 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -67,7 +67,6 @@ static inline bool hidh_interface_open(uint8_t dev_addr, uint8_t interface_numbe static inline void hidh_interface_close(hidh_interface_info_t *p_hid) { - (void) hcd_pipe_close(p_hid->pipe_hdl); tu_memclr(p_hid, sizeof(hidh_interface_info_t)); } diff --git a/src/class/msc/msc_host.c b/src/class/msc/msc_host.c index 0b1359264..2c9b2dec7 100644 --- a/src/class/msc/msc_host.c +++ b/src/class/msc/msc_host.c @@ -413,9 +413,6 @@ void msch_isr(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t x void msch_close(uint8_t dev_addr) { - (void) hcd_pipe_close(TUH_OPT_RHPORT, dev_addr, msch_data[dev_addr-1].ep_in); - (void) hcd_pipe_close(TUH_OPT_RHPORT, dev_addr, msch_data[dev_addr-1].ep_out); - tu_memclr(&msch_data[dev_addr-1], sizeof(msch_interface_t)); osal_semaphore_reset(msch_sem_hdl); diff --git a/src/common/tusb_types.h b/src/common/tusb_types.h index 8be1e87f6..d0a10acef 100644 --- a/src/common/tusb_types.h +++ b/src/common/tusb_types.h @@ -184,11 +184,6 @@ typedef enum TUSB_DEVICE_STATE_ADDRESSED , TUSB_DEVICE_STATE_CONFIGURED , TUSB_DEVICE_STATE_SUSPENDED , - - TUSB_DEVICE_STATE_REMOVING , - TUSB_DEVICE_STATE_SAFE_REMOVE , - - TUSB_DEVICE_STATE_INVALID_PARAMETER }tusb_device_state_t; typedef enum diff --git a/src/host/ehci/ehci.c b/src/host/ehci/ehci.c index 1b5289333..91a87f9d2 100644 --- a/src/host/ehci/ehci.c +++ b/src/host/ehci/ehci.c @@ -113,7 +113,7 @@ static inline ehci_qtd_t* qtd_find_free(uint8_t dev_addr) ATTR_PURE ATTR_ALWAYS static inline ehci_qtd_t* qtd_next(ehci_qtd_t const * p_qtd ) ATTR_PURE ATTR_ALWAYS_INLINE; static inline void qtd_insert_to_qhd(ehci_qhd_t *p_qhd, ehci_qtd_t *p_qtd_new) ATTR_ALWAYS_INLINE; static inline void qtd_remove_1st_from_qhd(ehci_qhd_t *p_qhd) ATTR_ALWAYS_INLINE; -static void qtd_init(ehci_qtd_t* p_qtd, uint32_t data_ptr, uint16_t total_bytes); +static void qtd_init (ehci_qtd_t* p_qtd, void* buffer, uint16_t total_bytes); static inline void list_insert(ehci_link_t *current, ehci_link_t *new, uint8_t new_type) ATTR_ALWAYS_INLINE; static inline ehci_link_t* list_next(ehci_link_t *p_link_pointer) ATTR_PURE ATTR_ALWAYS_INLINE; @@ -149,10 +149,53 @@ tusb_speed_t hcd_port_speed_get(uint8_t hostid) return (tusb_speed_t) ehci_data.regs->portsc_bm.nxp_port_speed; // NXP specific port speed } -// TODO refractor abtract later +static void list_remove_qhd_by_addr(ehci_link_t* list_head, uint8_t dev_addr) +{ + for(ehci_link_t* prev = list_head; + !prev->terminate && (tu_align32(prev->address) != (uint32_t) list_head); + prev = list_next(prev) ) + { + // TODO check type for ISO iTD and siTD + ehci_qhd_t* qhd = (ehci_qhd_t*) list_next(prev); + if ( qhd->dev_addr == dev_addr ) + { + // TODO deactive all TD, wait for QHD to inactive before removal + prev->address = qhd->next.address; + + // EHCI 4.8.2 link the removed qhd to async head (which always reachable by Host Controller) + qhd->next.address = ((uint32_t) list_head) | (EHCI_QTYPE_QHD << 1); + + if ( qhd->int_smask ) + { + // period list queue element is guarantee to be free in the next frame (1 ms) + qhd->used = 0; + }else + { + // async list use async advance handshake + // mark as removing, will completely re-usable when async advance isr occurs + qhd->removing = 1; + } + } + } +} + +// Close all opened endpoint belong to this device void hcd_device_remove(uint8_t rhport, uint8_t dev_addr) { - ehci_data.regs->command_bm.async_adv_doorbell = 1; // Async doorbell check EHCI 4.8.2 for operational details + // skip dev0 + if (dev_addr == 0) return; + + // Remove from async list + list_remove_qhd_by_addr( (ehci_link_t*) qhd_async_head(rhport), dev_addr ); + + // Remove from all interval period list + for(uint8_t i = 0; i < TU_ARRAY_SZIE(ehci_data.period_head_arr); i++) + { + list_remove_qhd_by_addr( (ehci_link_t*) &ehci_data.period_head_arr[i], dev_addr); + } + + // Async doorbell (EHCI 4.8.2 for operational details) + ehci_data.regs->command_bm.async_adv_doorbell = 1; } // EHCI controller init @@ -184,7 +227,6 @@ static bool ehci_init(uint8_t hostid) //------------- Periodic List -------------// // Build the polling interval tree with 1 ms, 2 ms, 4 ms and 8 ms (framesize) only - for(uint32_t i=0; i<4; i++) { ehci_data.period_head_arr[i].int_smask = 1; // queue head in period list must have smask non-zero @@ -252,28 +294,6 @@ static tusb_error_t hcd_controller_stop(uint8_t hostid) //--------------------------------------------------------------------+ // CONTROL PIPE API //--------------------------------------------------------------------+ -bool hcd_pipe_control_close(uint8_t dev_addr) -{ - //------------- TODO pipe handle validate -------------// - ehci_qhd_t* p_qhd = qhd_control(dev_addr); - - p_qhd->removing = 1; - - if (dev_addr != 0) - { - TU_ASSERT( list_remove_qhd( (ehci_link_t*) qhd_async_head( _usbh_devices[dev_addr].rhport ), - (ehci_link_t*) p_qhd) ); - } - - return true; -} - -bool hcd_edpt_close(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) -{ - // FIXME control only for now - return hcd_pipe_control_close(dev_addr); -} - bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t buflen) { uint8_t const epnum = edpt_number(ep_addr); @@ -285,7 +305,7 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * ehci_qhd_t* qhd = qhd_control(dev_addr); ehci_qtd_t* qtd = qtd_control(dev_addr); - qtd_init(qtd, (uint32_t) buffer, buflen); + qtd_init(qtd, buffer, buflen); // first first data toggle is always 1 (data & setup stage) qtd->data_toggle = 1; @@ -306,20 +326,20 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet[8]) { - ehci_qhd_t* p_qhd = qhd_control(dev_addr); - ehci_qtd_t* p_setup = qtd_control(dev_addr); + ehci_qhd_t* qhd = &ehci_data.control[dev_addr].qhd; + ehci_qtd_t* td = &ehci_data.control[dev_addr].qtd; - qtd_init(p_setup, (uint32_t) setup_packet, 8); - p_setup->pid = EHCI_PID_SETUP; - p_setup->int_on_complete = 1; - p_setup->next.terminate = 1; + qtd_init(td, setup_packet, 8); + td->pid = EHCI_PID_SETUP; + td->int_on_complete = 1; + td->next.terminate = 1; // sw region - p_qhd->p_qtd_list_head = p_setup; - p_qhd->p_qtd_list_tail = p_setup; + qhd->p_qtd_list_head = td; + qhd->p_qtd_list_tail = td; // attach TD - p_qhd->qtd_overlay.next.address = (uint32_t) p_setup; + qhd->qtd_overlay.next.address = (uint32_t) td; return true; } @@ -384,8 +404,8 @@ bool hcd_pipe_queue_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t buffer[], ui TU_ASSERT(p_qtd); - qtd_init(p_qtd, (uint32_t) buffer, total_bytes); - p_qtd->pid = p_qhd->pid_non_control; + qtd_init(p_qtd, buffer, total_bytes); + p_qtd->pid = p_qhd->pid; //------------- insert TD to TD list -------------// qtd_insert_to_qhd(p_qhd, p_qtd); @@ -408,31 +428,6 @@ bool hcd_pipe_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t buffer[], uint16_t return true; } -/// pipe_close should only be called as a part of unmount/safe-remove process -bool hcd_pipe_close(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) -{ - ehci_qhd_t *p_qhd = qhd_get_from_addr(dev_addr, ep_addr); - - // async list needs async advance handshake to make sure host controller has released cached data - // non-control does not use async advance, it will eventually free by control pipe close - // period list queue element is guarantee to be free in the next frame (1 ms) - p_qhd->removing = 1; // TODO redundant, only apply to control queue head - - if ( p_qhd->int_smask == 0 ) - { - // Async list - TU_ASSERT( list_remove_qhd( (ehci_link_t*) qhd_async_head( _usbh_devices[dev_addr].rhport ), - (ehci_link_t*) p_qhd), false ); - } - else - { - TU_ASSERT( list_remove_qhd( get_period_head( _usbh_devices[dev_addr].rhport, p_qhd->interval_ms ), - (ehci_link_t*) p_qhd), false ); - } - - return true; -} - bool hcd_edpt_busy(uint8_t dev_addr, uint8_t ep_addr) { ehci_qhd_t *p_qhd = qhd_get_from_addr(dev_addr, ep_addr); @@ -457,47 +452,20 @@ bool hcd_edpt_clear_stall(uint8_t dev_addr, uint8_t ep_addr) // EHCI Interrupt Handler //--------------------------------------------------------------------+ -// async_advance is handshake between sw stack & ehci controller where ehci free all memory from an deleted queue head. -// In tinyusb, queue head is only removed when device is unplugged. So only control queue head is checked if removing -static void async_advance_isr(ehci_qhd_t * const async_head) +// async_advance is handshake between usb stack & ehci controller. +// This isr mean it is safe to modify previously removed queue head from async list. +// In tinyusb, queue head is only removed when device is unplugged. +static void async_advance_isr(uint8_t rhport) { - // TODO do we need to close addr0 - if (async_head->removing) // closing control pipe of addr0 - { - async_head->removing = 0; - async_head->p_qtd_list_head = async_head->p_qtd_list_tail = NULL; - async_head->qtd_overlay.halted = 1; - - _usbh_devices[0].state = TUSB_DEVICE_STATE_UNPLUG; - } + (void) rhport; - for(uint8_t dev_addr=1; dev_addr < CFG_TUSB_HOST_DEVICE_MAX; dev_addr++) + ehci_qhd_t* qhd_pool = ehci_data.qhd_pool; + for(uint32_t i = 0; i < HCD_MAX_ENDPOINT; i++) { - // check if control endpoint is removing - ehci_qhd_t *p_control_qhd = qhd_control(dev_addr); - - if ( p_control_qhd->removing ) + if ( qhd_pool[i].removing ) { - p_control_qhd->removing = 0; - p_control_qhd->used = 0; - - // Host Controller has cleaned up its cached data for this device, set state to unplug - _usbh_devices[dev_addr].state = TUSB_DEVICE_STATE_UNPLUG; - - for (uint8_t i=0; idev_addr, edpt_addr(p_qhd->ep_number, p_qhd->pid_non_control == EHCI_PID_IN ? 1 : 0), XFER_RESULT_SUCCESS, p_qhd->total_xferred_bytes); + hcd_event_xfer_complete(p_qhd->dev_addr, edpt_addr(p_qhd->ep_number, p_qhd->pid == EHCI_PID_IN ? 1 : 0), XFER_RESULT_SUCCESS, p_qhd->total_xferred_bytes); p_qhd->total_xferred_bytes = 0; } } @@ -621,7 +589,7 @@ static void qhd_xfer_error_isr(ehci_qhd_t * p_qhd) } // call USBH callback - hcd_event_xfer_complete(p_qhd->dev_addr, edpt_addr(p_qhd->ep_number, p_qhd->pid_non_control == EHCI_PID_IN ? 1 : 0), error_event, p_qhd->total_xferred_bytes); + hcd_event_xfer_complete(p_qhd->dev_addr, edpt_addr(p_qhd->ep_number, p_qhd->pid == EHCI_PID_IN ? 1 : 0), error_event, p_qhd->total_xferred_bytes); p_qhd->total_xferred_bytes = 0; } @@ -675,7 +643,7 @@ static void xfer_error_isr(uint8_t hostid) } //------------- Host Controller Driver's Interrupt Handler -------------// -void hal_hcd_isr(uint8_t hostid) +void hal_hcd_isr(uint8_t rhport) { ehci_registers_t* regs = ehci_data.regs; @@ -692,7 +660,7 @@ void hal_hcd_isr(uint8_t hostid) if (regs->portsc_bm.connect_status_change) { - port_connect_status_change_isr(hostid); + port_connect_status_change_isr(rhport); } regs->portsc |= port_status; // Acknowledge change bits in portsc @@ -700,27 +668,27 @@ void hal_hcd_isr(uint8_t hostid) if (int_status & EHCI_INT_MASK_ERROR) { - xfer_error_isr(hostid); + xfer_error_isr(rhport); } //------------- some QTD/SITD/ITD with IOC set is completed -------------// if (int_status & EHCI_INT_MASK_NXP_ASYNC) { - async_list_xfer_complete_isr( qhd_async_head(hostid) ); + async_list_xfer_complete_isr( qhd_async_head(rhport) ); } if (int_status & EHCI_INT_MASK_NXP_PERIODIC) { for (uint8_t i=1; i <= EHCI_FRAMELIST_SIZE; i *= 2) { - period_list_xfer_complete_isr( hostid, i ); + period_list_xfer_complete_isr( rhport, i ); } } //------------- There is some removed async previously -------------// if (int_status & EHCI_INT_MASK_ASYNC_ADVANCE) // need to place after EHCI_INT_MASK_NXP_ASYNC { - async_advance_isr( qhd_async_head(hostid) ); + async_advance_isr(rhport); } } @@ -758,7 +726,7 @@ static inline ehci_qhd_t* qhd_get_from_addr(uint8_t dev_addr, uint8_t ep_addr) for(uint32_t i=0; iremoving = 0; p_qhd->p_qtd_list_head = NULL; p_qhd->p_qtd_list_tail = NULL; - p_qhd->pid_non_control = edpt_dir(ep_desc->bEndpointAddress) ? EHCI_PID_IN : EHCI_PID_OUT; // PID for TD under this endpoint + p_qhd->pid = edpt_dir(ep_desc->bEndpointAddress) ? EHCI_PID_IN : EHCI_PID_OUT; // PID for TD under this endpoint //------------- active, but no TD list -------------// p_qhd->qtd_overlay.halted = 0; p_qhd->qtd_overlay.next.terminate = 1; p_qhd->qtd_overlay.alternate.terminate = 1; - if (TUSB_XFER_BULK == xfer_type && p_qhd->ep_speed == TUSB_SPEED_HIGH && p_qhd->pid_non_control == EHCI_PID_OUT) + if (TUSB_XFER_BULK == xfer_type && p_qhd->ep_speed == TUSB_SPEED_HIGH && p_qhd->pid == EHCI_PID_OUT) { p_qhd->qtd_overlay.ping_err = 1; // do PING for Highspeed Bulk OUT, EHCI section 4.11 } } -static void qtd_init(ehci_qtd_t* p_qtd, uint32_t data_ptr, uint16_t total_bytes) +static void qtd_init(ehci_qtd_t* p_qtd, void* buffer, uint16_t total_bytes) { tu_memclr(p_qtd, sizeof(ehci_qtd_t)); @@ -892,7 +860,7 @@ static void qtd_init(ehci_qtd_t* p_qtd, uint32_t data_ptr, uint16_t total_bytes) p_qtd->total_bytes = total_bytes; p_qtd->expected_bytes = total_bytes; - p_qtd->buffer[0] = data_ptr; + p_qtd->buffer[0] = (uint32_t) buffer; for(uint8_t i=1; i<5; i++) { p_qtd->buffer[i] |= tu_align4k( p_qtd->buffer[i-1] ) + 4096; @@ -911,33 +879,4 @@ static inline ehci_link_t* list_next(ehci_link_t *p_link_pointer) return (ehci_link_t*) tu_align32(p_link_pointer->address); } -static ehci_link_t* list_find_previous_item(ehci_link_t* p_head, ehci_link_t* p_current) -{ - ehci_link_t *p_prev = p_head; - uint32_t max_loop = 0; - while( (tu_align32(p_prev->address) != (uint32_t) p_head) && // not loop around - (tu_align32(p_prev->address) != (uint32_t) p_current) && // not found yet - !p_prev->terminate && // not advanceable - max_loop < HCD_MAX_ENDPOINT) - { - p_prev = list_next(p_prev); - max_loop++; - } - - return (tu_align32(p_prev->address) != (uint32_t) p_head) ? p_prev : NULL; -} - -static bool list_remove_qhd(ehci_link_t* p_head, ehci_link_t* p_remove) -{ - ehci_link_t *p_prev = list_find_previous_item(p_head, p_remove); - - TU_ASSERT(p_prev); - - p_prev->address = p_remove->address; - // EHCI 4.8.2 link the removing queue head to async/period head (which always reachable by Host Controller) - p_remove->address = ((uint32_t) p_head) | (EHCI_QTYPE_QHD << 1); - - return true; -} - #endif diff --git a/src/host/ehci/ehci.h b/src/host/ehci/ehci.h index d0d746706..c1c274793 100644 --- a/src/host/ehci/ehci.h +++ b/src/host/ehci/ehci.h @@ -184,7 +184,7 @@ typedef struct ATTR_ALIGNED(32) //--------------------------------------------------------------------+ uint8_t used; uint8_t removing; // removed from asyn list, waiting for async advance - uint8_t pid_non_control; + uint8_t pid; uint8_t interval_ms; // polling interval in frames (or milisecond) uint16_t total_xferred_bytes; // number of bytes xferred until a qtd with ioc bit set @@ -229,7 +229,8 @@ typedef struct ATTR_ALIGNED(32) { TU_VERIFY_STATIC( sizeof(ehci_itd_t) == 64, "size is not correct" ); /// Split (Full-Speed) Isochronous Transfer Descriptor -typedef struct ATTR_ALIGNED(32) { +typedef struct ATTR_ALIGNED(32) +{ // Word 0: Next Link Pointer ehci_link_t next; @@ -332,7 +333,8 @@ enum ehci_portsc_change_mask_{ EHCI_PORTSC_MASK_OVER_CURRENT_CHANGE }; -typedef volatile struct { +typedef volatile struct +{ union { uint32_t command; diff --git a/src/host/hcd.h b/src/host/hcd.h index 257a7da59..fb0612ed8 100644 --- a/src/host/hcd.h +++ b/src/host/hcd.h @@ -108,7 +108,7 @@ bool hcd_port_connect_status(uint8_t hostid) ATTR_PURE ATTR_WARN_UNUSED_RESULT; void hcd_port_reset(uint8_t hostid); tusb_speed_t hcd_port_speed_get(uint8_t hostid) ATTR_PURE ATTR_WARN_UNUSED_RESULT; // TODO make inline if possible -// Call by USBH after event device remove +// HCD closs all opened endpoints belong to this device void hcd_device_remove(uint8_t rhport, uint8_t dev_addr); //--------------------------------------------------------------------+ @@ -135,8 +135,7 @@ bool hcd_edpt_busy(uint8_t dev_addr, uint8_t ep_addr); bool hcd_edpt_stalled(uint8_t dev_addr, uint8_t ep_addr); bool hcd_edpt_clear_stall(uint8_t dev_addr, uint8_t ep_addr); -// TODO remove -bool hcd_edpt_close(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr); + bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t buflen); //--------------------------------------------------------------------+ @@ -145,7 +144,6 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * // TODO control xfer should be used via usbh layer bool hcd_pipe_queue_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t buffer[], uint16_t total_bytes); // only queue, not transferring yet bool hcd_pipe_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t buffer[], uint16_t total_bytes, bool int_on_complete); -bool hcd_pipe_close(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr); // TODO remove #if 0 tusb_error_t hcd_pipe_cancel()ATTR_WARN_UNUSED_RESULT; diff --git a/src/host/hub.c b/src/host/hub.c index 411e1ae95..e2e91d73d 100644 --- a/src/host/hub.c +++ b/src/host/hub.c @@ -251,9 +251,7 @@ void hub_isr(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xf void hub_close(uint8_t dev_addr) { - hcd_pipe_close(TUH_OPT_RHPORT, dev_addr, hub_data[dev_addr-1].ep_status); tu_memclr(&hub_data[dev_addr-1], sizeof(usbh_hub_t)); - // osal_semaphore_reset(hub_enum_sem_hdl); } diff --git a/src/host/usbh.c b/src/host/usbh.c index 456eff531..31024f1f7 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -118,7 +118,7 @@ static host_class_driver_t const usbh_class_drivers[] = #endif }; -enum { USBH_CLASS_DRIVER_COUNT = sizeof(usbh_class_drivers) / sizeof(host_class_driver_t) }; +enum { USBH_CLASS_DRIVER_COUNT = TU_ARRAY_SZIE(usbh_class_drivers) }; //--------------------------------------------------------------------+ // INTERNAL OBJECT & FUNCTION DECLARATION @@ -146,7 +146,7 @@ static void mark_interface_endpoint(uint8_t ep2drv[8][2], uint8_t const* p_desc, //--------------------------------------------------------------------+ tusb_device_state_t tuh_device_get_state (uint8_t const dev_addr) { - TU_ASSERT( dev_addr <= CFG_TUSB_HOST_DEVICE_MAX, TUSB_DEVICE_STATE_INVALID_PARAMETER); + TU_ASSERT( dev_addr <= CFG_TUSB_HOST_DEVICE_MAX, TUSB_DEVICE_STATE_UNPLUG); return (tusb_device_state_t) _usbh_devices[dev_addr].state; } @@ -241,13 +241,6 @@ tusb_error_t usbh_pipe_control_open(uint8_t dev_addr, uint8_t max_packet_size) return TUSB_ERROR_NONE; } -static inline tusb_error_t usbh_pipe_control_close(uint8_t dev_addr) -{ - hcd_edpt_close(_usbh_devices[dev_addr].rhport, dev_addr, 0); - - return TUSB_ERROR_NONE; -} - //--------------------------------------------------------------------+ // USBH-HCD ISR/Callback API //--------------------------------------------------------------------+ @@ -321,13 +314,12 @@ void hcd_event_device_remove(uint8_t hostid) // return true if found and unmounted device, false if cannot find static void usbh_device_unplugged(uint8_t rhport, uint8_t hub_addr, uint8_t hub_port) { - bool is_found = false; - //------------- find the all devices (star-network) under port that is unplugged -------------// for (uint8_t dev_addr = 0; dev_addr <= CFG_TUSB_HOST_DEVICE_MAX; dev_addr ++) { usbh_device_t* dev = &_usbh_devices[dev_addr]; + // TODO Hub multiple level if (dev->rhport == rhport && (hub_addr == 0 || dev->hub_addr == hub_addr) && // hub_addr == 0 & hub_port == 0 means roothub (hub_port == 0 || dev->hub_port == hub_port) && @@ -336,29 +328,17 @@ static void usbh_device_unplugged(uint8_t rhport, uint8_t hub_addr, uint8_t hub_ // Invoke callback before close driver if (tuh_umount_cb) tuh_umount_cb(dev_addr); - // TODO Hub multiple level // Close class driver for (uint8_t drv_id = 0; drv_id < USBH_CLASS_DRIVER_COUNT; drv_id++) usbh_class_drivers[drv_id].close(dev_addr); - // TODO refractor - // set to REMOVING to allow HCD to clean up its cached data for this device - // HCD must set this device's state to TUSB_DEVICE_STATE_UNPLUG when done - dev->state = TUSB_DEVICE_STATE_REMOVING; - memset(dev->itf2drv, 0xff, sizeof(dev->itf2drv)); // invalid mapping memset(dev->ep2drv , 0xff, sizeof(dev->ep2drv )); // invalid mapping - usbh_pipe_control_close(dev_addr); - -// hcd_device_remove(rhport, dev_addr); + hcd_device_remove(rhport, dev_addr); - is_found = true; + dev->state = TUSB_DEVICE_STATE_UNPLUG; } } - - // FIXME remove - if (is_found) hcd_device_remove(_usbh_devices[0].rhport, 0); - } //--------------------------------------------------------------------+ @@ -515,7 +495,7 @@ bool enum_task(hcd_event_t* event) new_dev->speed = dev0->speed; new_dev->state = TUSB_DEVICE_STATE_ADDRESSED; - usbh_pipe_control_close(0); // hcd_device_remove(rhport, 0); // close device 0 + hcd_device_remove(dev0->rhport, 0); // close device 0 dev0->state = TUSB_DEVICE_STATE_UNPLUG; // open control pipe for new address -- cgit v1.3.1 From 6d86db3977aa60963d78d1bceaa7e3def60f1957 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 12 Dec 2018 11:51:31 +0700 Subject: rename edpt_dir/number/addr to tu_edpt_* --- docs/porting.md | 6 +++--- examples/host/cdc_msc_hid/src/tusb_config.h | 2 +- src/class/cdc/cdc_device.h | 2 +- src/class/cdc/cdc_host.c | 2 +- src/class/custom/custom_device.c | 2 +- src/class/custom/custom_device.h | 2 +- src/class/hid/hid_device.c | 2 +- src/class/hid/hid_device.h | 2 +- src/class/msc/msc_device.h | 2 +- src/class/msc/msc_host.c | 2 +- src/common/tusb_types.h | 6 +++--- src/device/usbd.c | 10 ++++----- src/host/ehci/ehci.c | 30 +++++++++++--------------- src/host/ohci/ohci.c | 10 ++++----- src/host/usbh.c | 10 ++++----- src/portable/microchip/samd21/dcd_samd21.c | 24 ++++++++++----------- src/portable/microchip/samd51/dcd_samd51.c | 24 ++++++++++----------- src/portable/nordic/nrf5x/dcd_nrf5x.c | 22 +++++++++---------- src/portable/nxp/lpc11_13_15/dcd_lpc11_13_15.c | 6 +++--- src/portable/nxp/lpc17_40/dcd_lpc17_40.c | 8 +++---- src/portable/nxp/lpc18_43/dcd_lpc18_43.c | 24 ++++++++++----------- src/portable/nxp/lpc18_43/hcd_lpc18_43.c | 7 ++++++ tests/support/tusb_config.h | 2 +- 23 files changed, 104 insertions(+), 103 deletions(-) (limited to 'src/common') diff --git a/docs/porting.md b/docs/porting.md index 5a464fa6b..040112d9c 100644 --- a/docs/porting.md +++ b/docs/porting.md @@ -113,10 +113,10 @@ As before with `dcd_event_bus_signal` the first argument is the USB peripheral n Endpoints are the core of the USB data transfer process. They come in a few forms such as control, isochronous, bulk, and interrupt. We won't cover the details here except with some caveats in open below. In general, data is transferred by setting up a buffer of a given length to be transferred on a given endpoint address and then waiting for an interrupt to signal that the transfer is finished. Further details below. -Endpoints within USB have an address which encodes both the number and direction of an endpoint. TinyUSB provides `edpt_number` and `edpt_dir` to unpack this data from the address. Here is a snippet that does it. +Endpoints within USB have an address which encodes both the number and direction of an endpoint. TinyUSB provides `tu_edpt_number` and `tu_edpt_dir` to unpack this data from the address. Here is a snippet that does it. - uint8_t epnum = edpt_number(ep_addr); - uint8_t dir = edpt_dir(ep_addr); + uint8_t epnum = tu_edpt_number(ep_addr); + uint8_t dir = tu_edpt_dir(ep_addr); ##### dcd_edpt_open diff --git a/examples/host/cdc_msc_hid/src/tusb_config.h b/examples/host/cdc_msc_hid/src/tusb_config.h index 07764fa90..cc06ae93d 100644 --- a/examples/host/cdc_msc_hid/src/tusb_config.h +++ b/examples/host/cdc_msc_hid/src/tusb_config.h @@ -84,7 +84,7 @@ #define CFG_TUH_CDC 1 #define CFG_TUH_HID_KEYBOARD 0 #define CFG_TUH_HID_MOUSE 0 -#define CFG_TUSB_HOST_HID_GENERIC 0 // (not yet supported) +#define CFG_TUSB_HOST_HID_GENERIC 0 // (not yet supported) #define CFG_TUH_MSC 0 #define CFG_TUSB_HOST_DEVICE_MAX (CFG_TUH_HUB ? 5 : 1) // normal hub has 4 ports diff --git a/src/class/cdc/cdc_device.h b/src/class/cdc/cdc_device.h index 0a17aa916..9dd837d7d 100644 --- a/src/class/cdc/cdc_device.h +++ b/src/class/cdc/cdc_device.h @@ -116,7 +116,7 @@ void cdcd_init (void); tusb_error_t cdcd_open (uint8_t rhport, tusb_desc_interface_t const * p_interface_desc, uint16_t *p_length); bool cdcd_control_request (uint8_t rhport, tusb_control_request_t const * p_request); bool cdcd_control_request_complete (uint8_t rhport, tusb_control_request_t const * p_request); -tusb_error_t cdcd_xfer_cb (uint8_t rhport, uint8_t edpt_addr, xfer_result_t result, uint32_t xferred_bytes); +tusb_error_t cdcd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); void cdcd_reset (uint8_t rhport); #endif diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index 159a13990..d660cc39f 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -196,7 +196,7 @@ bool cdch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *it TU_ASSERT(hcd_edpt_open(rhport, dev_addr, ep_desc)); - if ( edpt_dir(ep_desc->bEndpointAddress) == TUSB_DIR_IN ) + if ( tu_edpt_dir(ep_desc->bEndpointAddress) == TUSB_DIR_IN ) { p_cdc->ep_in = ep_desc->bEndpointAddress; }else diff --git a/src/class/custom/custom_device.c b/src/class/custom/custom_device.c index 194963c17..5abffacf6 100644 --- a/src/class/custom/custom_device.c +++ b/src/class/custom/custom_device.c @@ -94,7 +94,7 @@ bool cusd_control_request(uint8_t rhport, tusb_control_request_t const * p_reque return false; } -tusb_error_t cusd_xfer_cb(uint8_t rhport, uint8_t edpt_addr, xfer_result_t event, uint32_t xferred_bytes) +tusb_error_t cusd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) { return TUSB_ERROR_NONE; } diff --git a/src/class/custom/custom_device.h b/src/class/custom/custom_device.h index 0a8f05e7d..f223a4d3c 100644 --- a/src/class/custom/custom_device.h +++ b/src/class/custom/custom_device.h @@ -66,7 +66,7 @@ void cusd_init(void); tusb_error_t cusd_open(uint8_t rhport, tusb_desc_interface_t const * p_interface_desc, uint16_t *p_length); bool cusd_control_request_st(uint8_t rhport, tusb_control_request_t const * p_request); bool cusd_control_request_complete (uint8_t rhport, tusb_control_request_t const * p_request); -tusb_error_t cusd_xfer_cb(uint8_t rhport, uint8_t edpt_addr, xfer_result_t event, uint32_t xferred_bytes); +tusb_error_t cusd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); void cusd_reset(uint8_t rhport); #endif diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index 6e2ea27db..fa76ee015 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -510,7 +510,7 @@ bool hidd_control_request_complete(uint8_t rhport, tusb_control_request_t const return true; } -tusb_error_t hidd_xfer_cb(uint8_t rhport, uint8_t edpt_addr, xfer_result_t event, uint32_t xferred_bytes) +tusb_error_t hidd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) { // nothing to do return TUSB_ERROR_NONE; diff --git a/src/class/hid/hid_device.h b/src/class/hid/hid_device.h index 7aff7f34d..42c61a47b 100644 --- a/src/class/hid/hid_device.h +++ b/src/class/hid/hid_device.h @@ -380,7 +380,7 @@ void hidd_init(void); tusb_error_t hidd_open(uint8_t rhport, tusb_desc_interface_t const * p_interface_desc, uint16_t *p_length); bool hidd_control_request(uint8_t rhport, tusb_control_request_t const * p_request); bool hidd_control_request_complete (uint8_t rhport, tusb_control_request_t const * p_request); -tusb_error_t hidd_xfer_cb(uint8_t rhport, uint8_t edpt_addr, xfer_result_t event, uint32_t xferred_bytes); +tusb_error_t hidd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); void hidd_reset(uint8_t rhport); #endif diff --git a/src/class/msc/msc_device.h b/src/class/msc/msc_device.h index 4053679b8..55bfba83c 100644 --- a/src/class/msc/msc_device.h +++ b/src/class/msc/msc_device.h @@ -174,7 +174,7 @@ void mscd_init(void); tusb_error_t mscd_open(uint8_t rhport, tusb_desc_interface_t const * p_interface_desc, uint16_t *p_length); bool mscd_control_request(uint8_t rhport, tusb_control_request_t const * p_request); bool mscd_control_request_complete (uint8_t rhport, tusb_control_request_t const * p_request); -tusb_error_t mscd_xfer_cb(uint8_t rhport, uint8_t edpt_addr, xfer_result_t event, uint32_t xferred_bytes); +tusb_error_t mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); void mscd_reset(uint8_t rhport); #endif diff --git a/src/class/msc/msc_host.c b/src/class/msc/msc_host.c index 2c9b2dec7..dd771440d 100644 --- a/src/class/msc/msc_host.c +++ b/src/class/msc/msc_host.c @@ -309,7 +309,7 @@ bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *it TU_ASSERT(hcd_edpt_open(rhport, dev_addr, ep_desc)); - if ( edpt_dir(ep_desc->bEndpointAddress) == TUSB_DIR_IN ) + if ( tu_edpt_dir(ep_desc->bEndpointAddress) == TUSB_DIR_IN ) { p_msc->ep_in = ep_desc->bEndpointAddress; }else diff --git a/src/common/tusb_types.h b/src/common/tusb_types.h index d0a10acef..cbddd4156 100644 --- a/src/common/tusb_types.h +++ b/src/common/tusb_types.h @@ -376,18 +376,18 @@ static inline uint8_t bm_request_type(uint8_t direction, uint8_t type, uint8_t r //--------------------------------------------------------------------+ // Get direction from Endpoint address -static inline tusb_dir_t edpt_dir(uint8_t addr) +static inline tusb_dir_t tu_edpt_dir(uint8_t addr) { return (addr & TUSB_DIR_IN_MASK) ? TUSB_DIR_IN : TUSB_DIR_OUT; } // Get Endpoint number from address -static inline uint8_t edpt_number(uint8_t addr) +static inline uint8_t tu_edpt_number(uint8_t addr) { return addr & (~TUSB_DIR_IN_MASK); } -static inline uint8_t edpt_addr(uint8_t num, uint8_t dir) +static inline uint8_t tu_edpt_addr(uint8_t num, uint8_t dir) { return num | (dir ? TUSB_DIR_IN_MASK : 0); } diff --git a/src/device/usbd.c b/src/device/usbd.c index ad40e3c9f..b63dcb131 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -246,14 +246,14 @@ static void usbd_task_body(void) // Invoke the class callback associated with the endpoint address uint8_t const ep_addr = event.xfer_complete.ep_addr; - if ( 0 == edpt_number(ep_addr) ) + if ( 0 == tu_edpt_number(ep_addr) ) { // control transfer DATA stage callback usbd_control_xfer_cb(event.rhport, ep_addr, event.xfer_complete.result, event.xfer_complete.len); } else { - uint8_t const drv_id = _usbd_dev.ep2drv[edpt_number(ep_addr)][edpt_dir(ep_addr)]; + uint8_t const drv_id = _usbd_dev.ep2drv[tu_edpt_number(ep_addr)][tu_edpt_dir(ep_addr)]; TU_ASSERT(drv_id < USBD_CLASS_DRIVER_COUNT,); usbd_class_drivers[drv_id].xfer_cb(event.rhport, ep_addr, event.xfer_complete.result, event.xfer_complete.len); @@ -484,7 +484,7 @@ static void mark_interface_endpoint(uint8_t ep2drv[8][2], uint8_t const* p_desc, { uint8_t const ep_addr = ((tusb_desc_endpoint_t const*) p_desc)->bEndpointAddress; - ep2drv[edpt_number(ep_addr)][edpt_dir(ep_addr)] = driver_id; + ep2drv[tu_edpt_number(ep_addr)][tu_edpt_dir(ep_addr)] = driver_id; } len += descriptor_len(p_desc); @@ -576,7 +576,7 @@ void dcd_event_handler(dcd_event_t const * event, bool in_isr) case DCD_EVENT_XFER_COMPLETE: // skip zero-length control status complete event, should dcd notifies us. - if ( 0 == edpt_number(event->xfer_complete.ep_addr) && event->xfer_complete.len == 0) break; + if ( 0 == tu_edpt_number(event->xfer_complete.ep_addr) && event->xfer_complete.len == 0) break; osal_queue_send(_usbd_q, event, in_isr); TU_ASSERT(event->xfer_complete.result == XFER_RESULT_SUCCESS,); @@ -633,7 +633,7 @@ tusb_error_t usbd_open_edpt_pair(uint8_t rhport, tusb_desc_endpoint_t const* ep_ TU_ASSERT( dcd_edpt_open(rhport, ep_desc), TUSB_ERROR_DCD_OPEN_PIPE_FAILED ); - if ( edpt_dir(ep_desc->bEndpointAddress) == TUSB_DIR_IN ) + if ( tu_edpt_dir(ep_desc->bEndpointAddress) == TUSB_DIR_IN ) { (*ep_in) = ep_desc->bEndpointAddress; }else diff --git a/src/host/ehci/ehci.c b/src/host/ehci/ehci.c index ef5510a6d..278765585 100644 --- a/src/host/ehci/ehci.c +++ b/src/host/ehci/ehci.c @@ -48,9 +48,6 @@ #include "../usbh_hcd.h" #include "ehci.h" -// TODO remove -#include "chip.h" - //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ @@ -61,13 +58,8 @@ // Periodic frame list must be 4K alignment CFG_TUSB_MEM_SECTION ATTR_ALIGNED(4096) static ehci_data_t ehci_data; -//------------- Validation -------------// -// TODO static assert for memory placement on some known MCU such as lpc43xx - -uint32_t hcd_ehci_register_addr(uint8_t rhport) -{ - return (uint32_t) (rhport ? &LPC_USB1->USBCMD_H : &LPC_USB0->USBCMD_H ); -} +// EHCI portable +uint32_t hcd_ehci_register_addr(uint8_t rhport); //--------------------------------------------------------------------+ // PROTOTYPE @@ -279,7 +271,8 @@ static bool ehci_init(uint8_t hostid) return true; } -static void hcd_controller_stop(uint8_t rhport) +#if 0 +static void ehci_stop(uint8_t rhport) { (void) rhport; @@ -290,6 +283,7 @@ static void hcd_controller_stop(uint8_t rhport) // USB Spec: controller has to stop within 16 uframe = 2 frames while( regs->status_bm.hc_halted == 0 ) {} } +#endif //--------------------------------------------------------------------+ // CONTROL PIPE API @@ -298,8 +292,8 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * { (void) rhport; - uint8_t const epnum = edpt_number(ep_addr); - uint8_t const dir = edpt_dir(ep_addr); + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); // FIXME control only for now if ( epnum == 0 ) @@ -505,7 +499,7 @@ static void qhd_xfer_complete_isr(ehci_qhd_t * p_qhd) { // end of request // call USBH callback - hcd_event_xfer_complete(p_qhd->dev_addr, edpt_addr(p_qhd->ep_number, p_qhd->pid == EHCI_PID_IN ? 1 : 0), XFER_RESULT_SUCCESS, p_qhd->total_xferred_bytes); + hcd_event_xfer_complete(p_qhd->dev_addr, tu_edpt_addr(p_qhd->ep_number, p_qhd->pid == EHCI_PID_IN ? 1 : 0), XFER_RESULT_SUCCESS, p_qhd->total_xferred_bytes); p_qhd->total_xferred_bytes = 0; } } @@ -592,7 +586,7 @@ static void qhd_xfer_error_isr(ehci_qhd_t * p_qhd) } // call USBH callback - hcd_event_xfer_complete(p_qhd->dev_addr, edpt_addr(p_qhd->ep_number, p_qhd->pid == EHCI_PID_IN ? 1 : 0), error_event, p_qhd->total_xferred_bytes); + hcd_event_xfer_complete(p_qhd->dev_addr, tu_edpt_addr(p_qhd->ep_number, p_qhd->pid == EHCI_PID_IN ? 1 : 0), error_event, p_qhd->total_xferred_bytes); p_qhd->total_xferred_bytes = 0; } @@ -718,7 +712,7 @@ static inline ehci_qhd_t* qhd_get_from_addr(uint8_t dev_addr, uint8_t ep_addr) for(uint32_t i=0; idev_addr = dev_addr; p_qhd->fl_inactive_next_xact = 0; - p_qhd->ep_number = edpt_number(ep_desc->bEndpointAddress); + p_qhd->ep_number = tu_edpt_number(ep_desc->bEndpointAddress); p_qhd->ep_speed = _usbh_devices[dev_addr].speed; p_qhd->data_toggle_control= (xfer_type == TUSB_XFER_CONTROL) ? 1 : 0; p_qhd->head_list_flag = (dev_addr == 0) ? 1 : 0; // addr0's endpoint is the static asyn list head @@ -826,7 +820,7 @@ static void qhd_init(ehci_qhd_t *p_qhd, uint8_t dev_addr, tusb_desc_endpoint_t c p_qhd->removing = 0; p_qhd->p_qtd_list_head = NULL; p_qhd->p_qtd_list_tail = NULL; - p_qhd->pid = edpt_dir(ep_desc->bEndpointAddress) ? EHCI_PID_IN : EHCI_PID_OUT; // PID for TD under this endpoint + p_qhd->pid = tu_edpt_dir(ep_desc->bEndpointAddress) ? EHCI_PID_IN : EHCI_PID_OUT; // PID for TD under this endpoint //------------- active, but no TD list -------------// p_qhd->qtd_overlay.halted = 0; diff --git a/src/host/ohci/ohci.c b/src/host/ohci/ohci.c index c35eaa77b..bebb8a2ef 100644 --- a/src/host/ohci/ohci.c +++ b/src/host/ohci/ohci.c @@ -315,8 +315,8 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * { (void) rhport; - uint8_t const epnum = edpt_number(ep_addr); - uint8_t const dir = edpt_dir(ep_addr); + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); // FIXME control only for now if ( epnum == 0 ) @@ -344,14 +344,14 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * //--------------------------------------------------------------------+ static inline ohci_ed_t * ed_from_addr(uint8_t dev_addr, uint8_t ep_addr) { - if ( edpt_number(ep_addr) == 0 ) return &ohci_data.control[dev_addr].ed; + if ( tu_edpt_number(ep_addr) == 0 ) return &ohci_data.control[dev_addr].ed; ohci_ed_t* ed_pool = ohci_data.ed_pool; for(uint32_t i=0; idev_addr, - edpt_addr(p_ed->ep_number, p_ed->pid == OHCI_PID_IN), + tu_edpt_addr(p_ed->ep_number, p_ed->pid == OHCI_PID_IN), event, xferred_bytes); } diff --git a/src/host/usbh.c b/src/host/usbh.c index 962dc04dc..369ddd2a5 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -205,12 +205,12 @@ bool usbh_control_xfer (uint8_t dev_addr, tusb_control_request_t* request, uint8 // Data stage : first data toggle is always 1 if ( request->wLength ) { - hcd_edpt_xfer(rhport, dev_addr, edpt_addr(0, request->bmRequestType_bit.direction), data, request->wLength); + hcd_edpt_xfer(rhport, dev_addr, tu_edpt_addr(0, request->bmRequestType_bit.direction), data, request->wLength); TU_VERIFY(osal_semaphore_wait(dev->control.sem_hdl, OSAL_TIMEOUT_NORMAL)); } // Status : data toggle is always 1 - hcd_edpt_xfer(rhport, dev_addr, edpt_addr(0, 1-request->bmRequestType_bit.direction), NULL, 0); + hcd_edpt_xfer(rhport, dev_addr, tu_edpt_addr(0, 1-request->bmRequestType_bit.direction), NULL, 0); TU_VERIFY(osal_semaphore_wait(dev->control.sem_hdl, OSAL_TIMEOUT_NORMAL)); osal_mutex_unlock(dev->control.mutex_hdl); @@ -249,7 +249,7 @@ void hcd_event_xfer_complete(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t ev { usbh_device_t* dev = &_usbh_devices[ dev_addr ]; - if (0 == edpt_number(ep_addr)) + if (0 == tu_edpt_number(ep_addr)) { dev->control.pipe_status = event; // usbh_devices[ pipe_hdl.dev_addr ].control.xferred_bytes = xferred_bytes; not yet neccessary @@ -257,7 +257,7 @@ void hcd_event_xfer_complete(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t ev } else { - uint8_t drv_id = dev->ep2drv[edpt_number(ep_addr)][edpt_dir(ep_addr)]; + uint8_t drv_id = dev->ep2drv[tu_edpt_number(ep_addr)][tu_edpt_dir(ep_addr)]; TU_ASSERT(drv_id < USBH_CLASS_DRIVER_COUNT, ); if (usbh_class_drivers[drv_id].isr) @@ -689,7 +689,7 @@ static void mark_interface_endpoint(uint8_t ep2drv[8][2], uint8_t const* p_desc, { uint8_t const ep_addr = ((tusb_desc_endpoint_t const*) p_desc)->bEndpointAddress; - ep2drv[ edpt_number(ep_addr) ][ edpt_dir(ep_addr) ] = driver_id; + ep2drv[ tu_edpt_number(ep_addr) ][ tu_edpt_dir(ep_addr) ] = driver_id; } len += descriptor_len(p_desc); diff --git a/src/portable/microchip/samd21/dcd_samd21.c b/src/portable/microchip/samd21/dcd_samd21.c index 57c4c4d9d..af0721ec3 100644 --- a/src/portable/microchip/samd21/dcd_samd21.c +++ b/src/portable/microchip/samd21/dcd_samd21.c @@ -132,8 +132,8 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) { (void) rhport; - uint8_t const epnum = edpt_number(desc_edpt->bEndpointAddress); - uint8_t const dir = edpt_dir(desc_edpt->bEndpointAddress); + uint8_t const epnum = tu_edpt_number(desc_edpt->bEndpointAddress); + uint8_t const dir = tu_edpt_dir(desc_edpt->bEndpointAddress); UsbDeviceDescBank* bank = &sram_registers[epnum][dir]; uint32_t size_value = 0; @@ -168,8 +168,8 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t { (void) rhport; - uint8_t const epnum = edpt_number(ep_addr); - uint8_t const dir = edpt_dir(ep_addr); + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); UsbDeviceDescBank* bank = &sram_registers[epnum][dir]; UsbDeviceEndpoint* ep = &USB->DEVICE.DeviceEndpoint[epnum]; @@ -208,19 +208,19 @@ bool dcd_edpt_stalled (uint8_t rhport, uint8_t ep_addr) return false; } - uint8_t const epnum = edpt_number(ep_addr); + uint8_t const epnum = tu_edpt_number(ep_addr); UsbDeviceEndpoint* ep = &USB->DEVICE.DeviceEndpoint[epnum]; - return (edpt_dir(ep_addr) == TUSB_DIR_IN ) ? ep->EPINTFLAG.bit.STALL1 : ep->EPINTFLAG.bit.STALL0; + return (tu_edpt_dir(ep_addr) == TUSB_DIR_IN ) ? ep->EPINTFLAG.bit.STALL1 : ep->EPINTFLAG.bit.STALL0; } void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr) { (void) rhport; - uint8_t const epnum = edpt_number(ep_addr); + uint8_t const epnum = tu_edpt_number(ep_addr); UsbDeviceEndpoint* ep = &USB->DEVICE.DeviceEndpoint[epnum]; - if (edpt_dir(ep_addr) == TUSB_DIR_IN) { + if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN) { ep->EPSTATUSSET.reg = USB_DEVICE_EPSTATUSSET_STALLRQ1; } else { ep->EPSTATUSSET.reg = USB_DEVICE_EPSTATUSSET_STALLRQ0; @@ -236,10 +236,10 @@ void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr) { (void) rhport; - uint8_t const epnum = edpt_number(ep_addr); + uint8_t const epnum = tu_edpt_number(ep_addr); UsbDeviceEndpoint* ep = &USB->DEVICE.DeviceEndpoint[epnum]; - if (edpt_dir(ep_addr) == TUSB_DIR_IN) { + if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN) { ep->EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSCLR_STALLRQ1; } else { ep->EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSCLR_STALLRQ0; @@ -253,10 +253,10 @@ bool dcd_edpt_busy (uint8_t rhport, uint8_t ep_addr) // USBD shouldn't check control endpoint state if ( 0 == ep_addr ) return false; - uint8_t const epnum = edpt_number(ep_addr); + uint8_t const epnum = tu_edpt_number(ep_addr); UsbDeviceEndpoint* ep = &USB->DEVICE.DeviceEndpoint[epnum]; - if (edpt_dir(ep_addr) == TUSB_DIR_IN) { + if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN) { return ep->EPINTFLAG.bit.TRCPT1 == 0 && ep->EPSTATUS.bit.BK1RDY == 1; } return ep->EPINTFLAG.bit.TRCPT0 == 0 && ep->EPSTATUS.bit.BK0RDY == 1; diff --git a/src/portable/microchip/samd51/dcd_samd51.c b/src/portable/microchip/samd51/dcd_samd51.c index ba53d5598..ce66b8245 100644 --- a/src/portable/microchip/samd51/dcd_samd51.c +++ b/src/portable/microchip/samd51/dcd_samd51.c @@ -137,8 +137,8 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) { (void) rhport; - uint8_t const epnum = edpt_number(desc_edpt->bEndpointAddress); - uint8_t const dir = edpt_dir(desc_edpt->bEndpointAddress); + uint8_t const epnum = tu_edpt_number(desc_edpt->bEndpointAddress); + uint8_t const dir = tu_edpt_dir(desc_edpt->bEndpointAddress); UsbDeviceDescBank* bank = &sram_registers[epnum][dir]; uint32_t size_value = 0; @@ -173,8 +173,8 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t { (void) rhport; - uint8_t const epnum = edpt_number(ep_addr); - uint8_t const dir = edpt_dir(ep_addr); + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); UsbDeviceDescBank* bank = &sram_registers[epnum][dir]; UsbDeviceEndpoint* ep = &USB->DEVICE.DeviceEndpoint[epnum]; @@ -212,19 +212,19 @@ bool dcd_edpt_stalled (uint8_t rhport, uint8_t ep_addr) return false; } - uint8_t const epnum = edpt_number(ep_addr); + uint8_t const epnum = tu_edpt_number(ep_addr); UsbDeviceEndpoint* ep = &USB->DEVICE.DeviceEndpoint[epnum]; - return (edpt_dir(ep_addr) == TUSB_DIR_IN ) ? ep->EPINTFLAG.bit.STALL1 : ep->EPINTFLAG.bit.STALL0; + return (tu_edpt_dir(ep_addr) == TUSB_DIR_IN ) ? ep->EPINTFLAG.bit.STALL1 : ep->EPINTFLAG.bit.STALL0; } void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr) { (void) rhport; - uint8_t const epnum = edpt_number(ep_addr); + uint8_t const epnum = tu_edpt_number(ep_addr); UsbDeviceEndpoint* ep = &USB->DEVICE.DeviceEndpoint[epnum]; - if (edpt_dir(ep_addr) == TUSB_DIR_IN) { + if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN) { ep->EPSTATUSSET.reg = USB_DEVICE_EPSTATUSSET_STALLRQ1; } else { ep->EPSTATUSSET.reg = USB_DEVICE_EPSTATUSSET_STALLRQ0; @@ -240,10 +240,10 @@ void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr) { (void) rhport; - uint8_t const epnum = edpt_number(ep_addr); + uint8_t const epnum = tu_edpt_number(ep_addr); UsbDeviceEndpoint* ep = &USB->DEVICE.DeviceEndpoint[epnum]; - if (edpt_dir(ep_addr) == TUSB_DIR_IN) { + if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN) { ep->EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSCLR_STALLRQ1; } else { ep->EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSCLR_STALLRQ0; @@ -257,10 +257,10 @@ bool dcd_edpt_busy (uint8_t rhport, uint8_t ep_addr) // USBD shouldn't check control endpoint state if ( 0 == ep_addr ) return false; - uint8_t const epnum = edpt_number(ep_addr); + uint8_t const epnum = tu_edpt_number(ep_addr); UsbDeviceEndpoint* ep = &USB->DEVICE.DeviceEndpoint[epnum]; - if (edpt_dir(ep_addr) == TUSB_DIR_IN) { + if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN) { return ep->EPINTFLAG.bit.TRCPT1 == 0 && ep->EPSTATUS.bit.BK1RDY == 1; } return ep->EPINTFLAG.bit.TRCPT0 == 0 && ep->EPSTATUS.bit.BK0RDY == 1; diff --git a/src/portable/nordic/nrf5x/dcd_nrf5x.c b/src/portable/nordic/nrf5x/dcd_nrf5x.c index c7a4f413f..ad5090eb0 100644 --- a/src/portable/nordic/nrf5x/dcd_nrf5x.c +++ b/src/portable/nordic/nrf5x/dcd_nrf5x.c @@ -225,8 +225,8 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) { (void) rhport; - uint8_t const epnum = edpt_number(desc_edpt->bEndpointAddress); - uint8_t const dir = edpt_dir(desc_edpt->bEndpointAddress); + uint8_t const epnum = tu_edpt_number(desc_edpt->bEndpointAddress); + uint8_t const dir = tu_edpt_dir(desc_edpt->bEndpointAddress); _dcd.xfer[epnum][dir].mps = desc_edpt->wMaxPacketSize.size; @@ -248,8 +248,8 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t { (void) rhport; - uint8_t const epnum = edpt_number(ep_addr); - uint8_t const dir = edpt_dir(ep_addr); + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); xfer_td_t* xfer = get_td(epnum, dir); @@ -295,15 +295,15 @@ bool dcd_edpt_stalled (uint8_t rhport, uint8_t ep_addr) // control is never got halted if ( ep_addr == 0 ) return false; - uint8_t const epnum = edpt_number(ep_addr); - return (edpt_dir(ep_addr) == TUSB_DIR_IN ) ? NRF_USBD->HALTED.EPIN[epnum] : NRF_USBD->HALTED.EPOUT[epnum]; + uint8_t const epnum = tu_edpt_number(ep_addr); + return (tu_edpt_dir(ep_addr) == TUSB_DIR_IN ) ? NRF_USBD->HALTED.EPIN[epnum] : NRF_USBD->HALTED.EPOUT[epnum]; } void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr) { (void) rhport; - if ( edpt_number(ep_addr) == 0 ) + if ( tu_edpt_number(ep_addr) == 0 ) { NRF_USBD->TASKS_EP0STALL = 1; }else @@ -318,7 +318,7 @@ void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr) { (void) rhport; - if ( edpt_number(ep_addr) ) + if ( tu_edpt_number(ep_addr) ) { NRF_USBD->EPSTALL = (USBD_EPSTALL_STALL_UnStall << USBD_EPSTALL_STALL_Pos) | ep_addr; __ISB(); __DSB(); @@ -330,10 +330,10 @@ bool dcd_edpt_busy (uint8_t rhport, uint8_t ep_addr) (void) rhport; // USBD shouldn't check control endpoint state - if ( 0 == edpt_number(ep_addr) ) return false; + if ( 0 == tu_edpt_number(ep_addr) ) return false; - uint8_t const epnum = edpt_number(ep_addr); - uint8_t const dir = edpt_dir(ep_addr); + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); xfer_td_t* xfer = get_td(epnum, dir); diff --git a/src/portable/nxp/lpc11_13_15/dcd_lpc11_13_15.c b/src/portable/nxp/lpc11_13_15/dcd_lpc11_13_15.c index aa7f5e7e6..c910bf1ec 100644 --- a/src/portable/nxp/lpc11_13_15/dcd_lpc11_13_15.c +++ b/src/portable/nxp/lpc11_13_15/dcd_lpc11_13_15.c @@ -189,7 +189,7 @@ void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { (void) rhport; - if ( edpt_number(ep_addr) == 0 ) + if ( tu_edpt_number(ep_addr) == 0 ) { // TODO cannot able to STALL Control OUT endpoint !!!!! FIXME try some walk-around _dcd.ep[0][0].stall = _dcd.ep[1][0].stall = 1; @@ -209,11 +209,11 @@ bool dcd_edpt_stalled(uint8_t rhport, uint8_t ep_addr) return _dcd.ep[ep_id][0].stall; } -void dcd_edpt_clear_stall(uint8_t rhport, uint8_t edpt_addr) +void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) { (void) rhport; - uint8_t const ep_id = ep_addr2id(edpt_addr); + uint8_t const ep_id = ep_addr2id(ep_addr); _dcd.ep[ep_id][0].stall = 0; _dcd.ep[ep_id][0].toggle_reset = 1; diff --git a/src/portable/nxp/lpc17_40/dcd_lpc17_40.c b/src/portable/nxp/lpc17_40/dcd_lpc17_40.c index 84eb0c121..82d3c3cac 100644 --- a/src/portable/nxp/lpc17_40/dcd_lpc17_40.c +++ b/src/portable/nxp/lpc17_40/dcd_lpc17_40.c @@ -285,7 +285,7 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc) { (void) rhport; - uint8_t const epnum = edpt_number(p_endpoint_desc->bEndpointAddress); + uint8_t const epnum = tu_edpt_number(p_endpoint_desc->bEndpointAddress); uint8_t const ep_id = ep_addr2idx(p_endpoint_desc->bEndpointAddress); // Endpoint type is fixed to endpoint number @@ -336,7 +336,7 @@ void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { (void) rhport; - if ( edpt_number(ep_addr) == 0 ) + if ( tu_edpt_number(ep_addr) == 0 ) { sie_write(SIE_CMDCODE_ENDPOINT_SET_STATUS+0, 1, SIE_SET_ENDPOINT_STALLED_MASK | SIE_SET_ENDPOINT_CONDITION_STALLED_MASK); }else @@ -394,9 +394,9 @@ static bool control_xact(uint8_t rhport, uint8_t dir, uint8_t * buffer, uint8_t bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes) { // Control transfer is not DMA support, and must be done in slave mode - if ( edpt_number(ep_addr) == 0 ) + if ( tu_edpt_number(ep_addr) == 0 ) { - return control_xact(rhport, edpt_dir(ep_addr), buffer, (uint8_t) total_bytes); + return control_xact(rhport, tu_edpt_dir(ep_addr), buffer, (uint8_t) total_bytes); } else { diff --git a/src/portable/nxp/lpc18_43/dcd_lpc18_43.c b/src/portable/nxp/lpc18_43/dcd_lpc18_43.c index d524d9dea..70b34d848 100644 --- a/src/portable/nxp/lpc18_43/dcd_lpc18_43.c +++ b/src/portable/nxp/lpc18_43/dcd_lpc18_43.c @@ -205,8 +205,8 @@ static void qtd_init(dcd_qtd_t* p_qtd, void * data_ptr, uint16_t total_bytes) //--------------------------------------------------------------------+ void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { - uint8_t const epnum = edpt_number(ep_addr); - uint8_t const dir = edpt_dir(ep_addr); + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); if ( epnum == 0) { @@ -220,16 +220,16 @@ void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) bool dcd_edpt_stalled (uint8_t rhport, uint8_t ep_addr) { - uint8_t const epnum = edpt_number(ep_addr); - uint8_t const dir = edpt_dir(ep_addr); + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); return LPC_USB[rhport]->ENDPTCTRL[epnum] & (ENDPTCTRL_MASK_STALL << (dir ? 16 : 0)); } void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) { - uint8_t const epnum = edpt_number(ep_addr); - uint8_t const dir = edpt_dir(ep_addr); + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); // data toggle also need to be reset LPC_USB[rhport]->ENDPTCTRL[epnum] |= ENDPTCTRL_MASK_TOGGLE_RESET << ( dir ? 16 : 0 ); @@ -241,8 +241,8 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc) // TODO not support ISO yet TU_VERIFY ( p_endpoint_desc->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS); - uint8_t const epnum = edpt_number(p_endpoint_desc->bEndpointAddress); - uint8_t const dir = edpt_dir(p_endpoint_desc->bEndpointAddress); + uint8_t const epnum = tu_edpt_number(p_endpoint_desc->bEndpointAddress); + uint8_t const dir = tu_edpt_dir(p_endpoint_desc->bEndpointAddress); uint8_t const ep_idx = 2*epnum + dir; // USB0 has 5, USB1 has 3 non-control endpoints @@ -264,8 +264,8 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc) bool dcd_edpt_busy(uint8_t rhport, uint8_t ep_addr) { - uint8_t const epnum = edpt_number(ep_addr); - uint8_t const dir = edpt_dir(ep_addr); + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); uint8_t const ep_idx = 2*epnum + dir; dcd_qtd_t * p_qtd = &dcd_data_ptr[rhport]->qtd[ep_idx]; @@ -276,8 +276,8 @@ bool dcd_edpt_busy(uint8_t rhport, uint8_t ep_addr) bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) { - uint8_t const epnum = edpt_number(ep_addr); - uint8_t const dir = edpt_dir(ep_addr); + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); uint8_t const ep_idx = 2*epnum + dir; if ( epnum == 0 ) diff --git a/src/portable/nxp/lpc18_43/hcd_lpc18_43.c b/src/portable/nxp/lpc18_43/hcd_lpc18_43.c index efdf8fea4..092030056 100644 --- a/src/portable/nxp/lpc18_43/hcd_lpc18_43.c +++ b/src/portable/nxp/lpc18_43/hcd_lpc18_43.c @@ -42,6 +42,8 @@ #include "chip.h" +// LPC18xx and 43xx use EHCI driver + void hcd_int_enable(uint8_t rhport) { NVIC_EnableIRQ(rhport ? USB1_IRQn : USB0_IRQn); @@ -52,4 +54,9 @@ void hcd_int_disable(uint8_t rhport) NVIC_DisableIRQ(rhport ? USB1_IRQn : USB0_IRQn); } +uint32_t hcd_ehci_register_addr(uint8_t rhport) +{ + return (uint32_t) (rhport ? &LPC_USB1->USBCMD_H : &LPC_USB0->USBCMD_H ); +} + #endif diff --git a/tests/support/tusb_config.h b/tests/support/tusb_config.h index 4ff3965e1..fe3d59ef1 100644 --- a/tests/support/tusb_config.h +++ b/tests/support/tusb_config.h @@ -55,7 +55,7 @@ #define CFG_TUSB_HOST_DEVICE_MAX 5 // TODO be a part of HUB config //------------- CLASS -------------// -#define CFG_TUH_HUB 0 +#define CFG_TUH_HUB 1 #define CFG_TUH_HID_KEYBOARD 1 #define CFG_TUH_HID_MOUSE 1 #define CFG_TUH_MSC 1 -- cgit v1.3.1 From 6c0b0917e15ca0acf7ce9bed0f3735a794abb807 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 12 Dec 2018 12:01:15 +0700 Subject: rename descriptor_* helper to tu_desc_* --- src/class/cdc/cdc_device.c | 18 +++++++++--------- src/class/cdc/cdc_host.c | 10 +++++----- src/class/custom/custom_device.c | 2 +- src/class/custom/custom_host.c | 4 ++-- src/class/msc/msc_device.c | 10 +++++----- src/class/msc/msc_host.c | 4 ++-- src/common/tusb_types.h | 13 +++++++------ src/device/usbd.c | 14 +++++++------- src/host/hub.c | 8 ++++---- src/host/usbh.c | 14 +++++++------- 10 files changed, 49 insertions(+), 48 deletions(-) (limited to 'src/common') diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index d477a0d23..a865ba3c5 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -229,13 +229,13 @@ void cdcd_reset(uint8_t rhport) } } -tusb_error_t cdcd_open(uint8_t rhport, tusb_desc_interface_t const * p_interface_desc, uint16_t *p_length) +tusb_error_t cdcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length) { - if ( CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL != p_interface_desc->bInterfaceSubClass) return TUSB_ERROR_CDC_UNSUPPORTED_SUBCLASS; + if ( CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL != itf_desc->bInterfaceSubClass) return TUSB_ERROR_CDC_UNSUPPORTED_SUBCLASS; // Only support AT commands, no protocol and vendor specific commands. - if ( !(tu_within(CDC_COMM_PROTOCOL_NONE, p_interface_desc->bInterfaceProtocol, CDC_COMM_PROTOCOL_ATCOMMAND_CDMA) || - p_interface_desc->bInterfaceProtocol == 0xff ) ) + if ( !(tu_within(CDC_COMM_PROTOCOL_NONE, itf_desc->bInterfaceProtocol, CDC_COMM_PROTOCOL_ATCOMMAND_CDMA) || + itf_desc->bInterfaceProtocol == 0xff ) ) { return TUSB_ERROR_CDC_UNSUPPORTED_PROTOCOL; } @@ -252,16 +252,16 @@ tusb_error_t cdcd_open(uint8_t rhport, tusb_desc_interface_t const * p_interface } //------------- Control Interface -------------// - p_cdc->itf_num = p_interface_desc->bInterfaceNumber; + p_cdc->itf_num = itf_desc->bInterfaceNumber; - uint8_t const * p_desc = descriptor_next ( (uint8_t const *) p_interface_desc ); + uint8_t const * p_desc = tu_desc_next( itf_desc ); (*p_length) = sizeof(tusb_desc_interface_t); // Communication Functional Descriptors while( TUSB_DESC_CLASS_SPECIFIC == p_desc[DESC_OFFSET_TYPE] ) { (*p_length) += p_desc[DESC_OFFSET_LEN]; - p_desc = descriptor_next(p_desc); + p_desc = tu_desc_next(p_desc); } if ( TUSB_DESC_ENDPOINT == p_desc[DESC_OFFSET_TYPE]) @@ -271,7 +271,7 @@ tusb_error_t cdcd_open(uint8_t rhport, tusb_desc_interface_t const * p_interface p_cdc->ep_notif = ((tusb_desc_endpoint_t const *) p_desc)->bEndpointAddress; (*p_length) += p_desc[DESC_OFFSET_LEN]; - p_desc = descriptor_next(p_desc); + p_desc = tu_desc_next(p_desc); } //------------- Data Interface (if any) -------------// @@ -280,7 +280,7 @@ tusb_error_t cdcd_open(uint8_t rhport, tusb_desc_interface_t const * p_interface { // next to endpoint descritpor (*p_length) += p_desc[DESC_OFFSET_LEN]; - p_desc = descriptor_next(p_desc); + p_desc = tu_desc_next(p_desc); // Open endpoint pair with usbd helper tusb_desc_endpoint_t const *p_desc_ep = (tusb_desc_endpoint_t const *) p_desc; diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index d660cc39f..d6767d0a7 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -146,7 +146,7 @@ bool cdch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *it uint8_t const * p_desc; cdch_data_t * p_cdc; - p_desc = descriptor_next ( (uint8_t const *) itf_desc ); + p_desc = tu_desc_next(itf_desc); p_cdc = &cdch_data[dev_addr-1]; p_cdc->itf_num = itf_desc->bInterfaceNumber; @@ -165,7 +165,7 @@ bool cdch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *it } (*p_length) += p_desc[DESC_OFFSET_LEN]; - p_desc = descriptor_next(p_desc); + p_desc = tu_desc_next(p_desc); } if ( TUSB_DESC_ENDPOINT == p_desc[DESC_OFFSET_TYPE]) @@ -177,7 +177,7 @@ bool cdch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *it p_cdc->ep_notif = ep_desc->bEndpointAddress; (*p_length) += p_desc[DESC_OFFSET_LEN]; - p_desc = descriptor_next(p_desc); + p_desc = tu_desc_next(p_desc); } //------------- Data Interface (if any) -------------// @@ -185,7 +185,7 @@ bool cdch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *it (TUSB_CLASS_CDC_DATA == ((tusb_desc_interface_t const *) p_desc)->bInterfaceClass) ) { (*p_length) += p_desc[DESC_OFFSET_LEN]; - p_desc = descriptor_next(p_desc); + p_desc = tu_desc_next(p_desc); // data endpoints expected to be in pairs for(uint32_t i=0; i<2; i++) @@ -205,7 +205,7 @@ bool cdch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *it } (*p_length) += p_desc[DESC_OFFSET_LEN]; - p_desc = descriptor_next( p_desc ); + p_desc = tu_desc_next( p_desc ); } } diff --git a/src/class/custom/custom_device.c b/src/class/custom/custom_device.c index 5abffacf6..bec6f42d1 100644 --- a/src/class/custom/custom_device.c +++ b/src/class/custom/custom_device.c @@ -76,7 +76,7 @@ tusb_error_t cusd_open(uint8_t rhport, tusb_desc_interface_t const * p_desc_itf, cusd_interface_t* p_itf = &_cusd_itf; // Open endpoint pair with usbd helper - tusb_desc_endpoint_t const *p_desc_ep = (tusb_desc_endpoint_t const *) descriptor_next( (uint8_t const*) p_desc_itf ); + tusb_desc_endpoint_t const *p_desc_ep = (tusb_desc_endpoint_t const *) tu_desc_next( (uint8_t const*) p_desc_itf ); TU_ASSERT_ERR( usbd_open_edpt_pair(rhport, p_desc_ep, TUSB_XFER_BULK, &p_itf->ep_out, &p_itf->ep_in) ); p_itf->itf_num = p_desc_itf->bInterfaceNumber; diff --git a/src/class/custom/custom_host.c b/src/class/custom/custom_host.c index e840a2829..894e641e8 100644 --- a/src/class/custom/custom_host.c +++ b/src/class/custom/custom_host.c @@ -111,7 +111,7 @@ tusb_error_t cush_open_subtask(uint8_t dev_addr, tusb_desc_interface_t const *p_ { // FIXME quick hack to test lpc1k custom class with 2 bulk endpoints uint8_t const *p_desc = (uint8_t const *) p_interface_desc; - p_desc = descriptor_next(p_desc); + p_desc = tu_desc_next(p_desc); //------------- Bulk Endpoints Descriptor -------------// for(uint32_t i=0; i<2; i++) @@ -124,7 +124,7 @@ tusb_error_t cush_open_subtask(uint8_t dev_addr, tusb_desc_interface_t const *p_ *p_pipe_hdl = hcd_edpt_open(dev_addr, p_endpoint, TUSB_CLASS_VENDOR_SPECIFIC); TU_ASSERT ( pipehandle_is_valid(*p_pipe_hdl), TUSB_ERROR_HCD_OPEN_PIPE_FAILED ); - p_desc = descriptor_next(p_desc); + p_desc = tu_desc_next(p_desc); } (*p_length) = sizeof(tusb_desc_interface_t) + 2*sizeof(tusb_desc_endpoint_t); diff --git a/src/class/msc/msc_device.c b/src/class/msc/msc_device.c index 83c9990d8..48f23688d 100644 --- a/src/class/msc/msc_device.c +++ b/src/class/msc/msc_device.c @@ -150,19 +150,19 @@ void mscd_reset(uint8_t rhport) tu_memclr(&_mscd_itf, sizeof(mscd_interface_t)); } -tusb_error_t mscd_open(uint8_t rhport, tusb_desc_interface_t const * p_desc_itf, uint16_t *p_len) +tusb_error_t mscd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_len) { // only support SCSI's BOT protocol - TU_VERIFY( ( MSC_SUBCLASS_SCSI == p_desc_itf->bInterfaceSubClass && - MSC_PROTOCOL_BOT == p_desc_itf->bInterfaceProtocol ), TUSB_ERROR_MSC_UNSUPPORTED_PROTOCOL ); + TU_VERIFY( ( MSC_SUBCLASS_SCSI == itf_desc->bInterfaceSubClass && + MSC_PROTOCOL_BOT == itf_desc->bInterfaceProtocol ), TUSB_ERROR_MSC_UNSUPPORTED_PROTOCOL ); mscd_interface_t * p_msc = &_mscd_itf; // Open endpoint pair with usbd helper - tusb_desc_endpoint_t const *p_desc_ep = (tusb_desc_endpoint_t const *) descriptor_next( (uint8_t const*) p_desc_itf ); + tusb_desc_endpoint_t const *p_desc_ep = (tusb_desc_endpoint_t const *) tu_desc_next( itf_desc ); TU_ASSERT_ERR( usbd_open_edpt_pair(rhport, p_desc_ep, TUSB_XFER_BULK, &p_msc->ep_out, &p_msc->ep_in) ); - p_msc->itf_num = p_desc_itf->bInterfaceNumber; + p_msc->itf_num = itf_desc->bInterfaceNumber; (*p_len) = sizeof(tusb_desc_interface_t) + 2*sizeof(tusb_desc_endpoint_t); //------------- Queue Endpoint OUT for Command Block Wrapper -------------// diff --git a/src/class/msc/msc_host.c b/src/class/msc/msc_host.c index dd771440d..86669b279 100644 --- a/src/class/msc/msc_host.c +++ b/src/class/msc/msc_host.c @@ -300,7 +300,7 @@ bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *it msch_interface_t* p_msc = &msch_data[dev_addr-1]; //------------- Open Data Pipe -------------// - tusb_desc_endpoint_t const * ep_desc = (tusb_desc_endpoint_t const *) descriptor_next( (uint8_t const*) itf_desc ); + tusb_desc_endpoint_t const * ep_desc = (tusb_desc_endpoint_t const *) tu_desc_next(itf_desc); for(uint32_t i=0; i<2; i++) { @@ -317,7 +317,7 @@ bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *it p_msc->ep_out = ep_desc->bEndpointAddress; } - ep_desc = (tusb_desc_endpoint_t const *) descriptor_next( (uint8_t const*) ep_desc ); + ep_desc = (tusb_desc_endpoint_t const *) tu_desc_next(ep_desc); } p_msc->itf_numr = itf_desc->bInterfaceNumber; diff --git a/src/common/tusb_types.h b/src/common/tusb_types.h index cbddd4156..cf02952ab 100644 --- a/src/common/tusb_types.h +++ b/src/common/tusb_types.h @@ -395,19 +395,20 @@ static inline uint8_t tu_edpt_addr(uint8_t num, uint8_t dir) //--------------------------------------------------------------------+ // Descriptor helper //--------------------------------------------------------------------+ -static inline uint8_t const * descriptor_next(uint8_t const p_desc[]) +static inline uint8_t const * tu_desc_next(void const* desc) { - return p_desc + p_desc[DESC_OFFSET_LEN]; + uint8_t const* desc8 = (uint8_t const*) desc; + return desc8 + desc8[DESC_OFFSET_LEN]; } -static inline uint8_t descriptor_type(uint8_t const p_desc[]) +static inline uint8_t tu_desc_type(void const* desc) { - return p_desc[DESC_OFFSET_TYPE]; + return ((uint8_t const*) desc)[DESC_OFFSET_TYPE]; } -static inline uint8_t descriptor_len(uint8_t const p_desc[]) +static inline uint8_t tu_desc_len(void const* desc) { - return p_desc[DESC_OFFSET_LEN]; + return ((uint8_t const*) desc)[DESC_OFFSET_LEN]; } // Length of the string descriptors in bytes with slen characters diff --git a/src/device/usbd.c b/src/device/usbd.c index b63dcb131..096437747 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -436,12 +436,12 @@ static bool process_set_config(uint8_t rhport) while( p_desc < desc_cfg + cfg_len ) { // Each interface always starts with Interface or Association descriptor - if ( TUSB_DESC_INTERFACE_ASSOCIATION == descriptor_type(p_desc) ) + if ( TUSB_DESC_INTERFACE_ASSOCIATION == tu_desc_type(p_desc) ) { - p_desc = descriptor_next(p_desc); // ignore Interface Association + p_desc = tu_desc_next(p_desc); // ignore Interface Association }else { - TU_ASSERT( TUSB_DESC_INTERFACE == descriptor_type(p_desc) ); + TU_ASSERT( TUSB_DESC_INTERFACE == tu_desc_type(p_desc) ); tusb_desc_interface_t* desc_itf = (tusb_desc_interface_t*) p_desc; @@ -480,15 +480,15 @@ static void mark_interface_endpoint(uint8_t ep2drv[8][2], uint8_t const* p_desc, while( len < desc_len ) { - if ( TUSB_DESC_ENDPOINT == descriptor_type(p_desc) ) + if ( TUSB_DESC_ENDPOINT == tu_desc_type(p_desc) ) { uint8_t const ep_addr = ((tusb_desc_endpoint_t const*) p_desc)->bEndpointAddress; ep2drv[tu_edpt_number(ep_addr)][tu_edpt_dir(ep_addr)] = driver_id; } - len += descriptor_len(p_desc); - p_desc = descriptor_next(p_desc); + len += tu_desc_len(p_desc); + p_desc = tu_desc_next(p_desc); } } @@ -641,7 +641,7 @@ tusb_error_t usbd_open_edpt_pair(uint8_t rhport, tusb_desc_endpoint_t const* ep_ (*ep_out) = ep_desc->bEndpointAddress; } - ep_desc = (tusb_desc_endpoint_t const *) descriptor_next( (uint8_t const*) ep_desc ); + ep_desc = (tusb_desc_endpoint_t const *) tu_desc_next(ep_desc); } return TUSB_ERROR_NONE; diff --git a/src/host/hub.c b/src/host/hub.c index e2e91d73d..e9f9dc7de 100644 --- a/src/host/hub.c +++ b/src/host/hub.c @@ -156,21 +156,21 @@ void hub_init(void) // hub_enum_sem_hdl = osal_semaphore_create( OSAL_SEM_REF(hub_enum_semaphore) ); } -bool hub_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *p_interface_desc, uint16_t *p_length) +bool hub_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t *p_length) { // not support multiple TT yet - if ( p_interface_desc->bInterfaceProtocol > 1 ) return false; + if ( itf_desc->bInterfaceProtocol > 1 ) return false; //------------- Open Interrupt Status Pipe -------------// tusb_desc_endpoint_t const *ep_desc; - ep_desc = (tusb_desc_endpoint_t const *) descriptor_next( (uint8_t const*) p_interface_desc ); + ep_desc = (tusb_desc_endpoint_t const *) tu_desc_next(itf_desc); TU_ASSERT(TUSB_DESC_ENDPOINT == ep_desc->bDescriptorType); TU_ASSERT(TUSB_XFER_INTERRUPT == ep_desc->bmAttributes.xfer); TU_ASSERT(hcd_edpt_open(rhport, dev_addr, ep_desc)); - hub_data[dev_addr-1].itf_num = p_interface_desc->bInterfaceNumber; + hub_data[dev_addr-1].itf_num = itf_desc->bInterfaceNumber; hub_data[dev_addr-1].ep_status = ep_desc->bEndpointAddress; (*p_length) = sizeof(tusb_desc_interface_t) + sizeof(tusb_desc_endpoint_t); diff --git a/src/host/usbh.c b/src/host/usbh.c index 369ddd2a5..bbe60362a 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -560,9 +560,9 @@ bool enum_task(hcd_event_t* event) while( p_desc < _usbh_ctrl_buf + ((tusb_desc_configuration_t*)_usbh_ctrl_buf)->wTotalLength ) { // skip until we see interface descriptor - if ( TUSB_DESC_INTERFACE != descriptor_type(p_desc) ) + if ( TUSB_DESC_INTERFACE != tu_desc_type(p_desc) ) { - p_desc = descriptor_next(p_desc); // skip the descriptor, increase by the descriptor's length + p_desc = tu_desc_next(p_desc); // skip the descriptor, increase by the descriptor's length }else { tusb_desc_interface_t* desc_itf = (tusb_desc_interface_t*) p_desc; @@ -577,7 +577,7 @@ bool enum_task(hcd_event_t* event) if( drv_id >= USBH_CLASS_DRIVER_COUNT ) { // skip unsupported class - p_desc = descriptor_next(p_desc); + p_desc = tu_desc_next(p_desc); } else { @@ -589,7 +589,7 @@ bool enum_task(hcd_event_t* event) { // TODO Attach hub to Hub is not currently supported // skip this interface - p_desc = descriptor_next(p_desc); + p_desc = tu_desc_next(p_desc); } else { @@ -685,15 +685,15 @@ static void mark_interface_endpoint(uint8_t ep2drv[8][2], uint8_t const* p_desc, while( len < desc_len ) { - if ( TUSB_DESC_ENDPOINT == descriptor_type(p_desc) ) + if ( TUSB_DESC_ENDPOINT == tu_desc_type(p_desc) ) { uint8_t const ep_addr = ((tusb_desc_endpoint_t const*) p_desc)->bEndpointAddress; ep2drv[ tu_edpt_number(ep_addr) ][ tu_edpt_dir(ep_addr) ] = driver_id; } - len += descriptor_len(p_desc); - p_desc = descriptor_next(p_desc); + len += tu_desc_len(p_desc); + p_desc = tu_desc_next(p_desc); } } -- cgit v1.3.1 From 5fd60e57617dab3afcb03d245c25b676ef4ab65f Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 12 Dec 2018 12:36:40 +0700 Subject: clean up --- src/common/tusb_types.h | 1 - src/host/usbh.c | 10 +++------- 2 files changed, 3 insertions(+), 8 deletions(-) (limited to 'src/common') diff --git a/src/common/tusb_types.h b/src/common/tusb_types.h index cf02952ab..6f0167898 100644 --- a/src/common/tusb_types.h +++ b/src/common/tusb_types.h @@ -181,7 +181,6 @@ enum { typedef enum { TUSB_DEVICE_STATE_UNPLUG = 0 , - TUSB_DEVICE_STATE_ADDRESSED , TUSB_DEVICE_STATE_CONFIGURED , TUSB_DEVICE_STATE_SUSPENDED , }tusb_device_state_t; diff --git a/src/host/usbh.c b/src/host/usbh.c index bbe60362a..39de4f7e7 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -438,7 +438,6 @@ bool enum_task(hcd_event_t* event) #endif TU_ASSERT_ERR( usbh_pipe_control_open(0, 8) ); - dev0->state = TUSB_DEVICE_STATE_ADDRESSED; //------------- Get first 8 bytes of device descriptor to get Control Endpoint Size -------------// request = (tusb_control_request_t ) { @@ -493,7 +492,6 @@ bool enum_task(hcd_event_t* event) new_dev->hub_addr = dev0->hub_addr; new_dev->hub_port = dev0->hub_port; new_dev->speed = dev0->speed; - new_dev->state = TUSB_DEVICE_STATE_ADDRESSED; hcd_device_close(dev0->rhport, 0); // close device 0 dev0->state = TUSB_DEVICE_STATE_UNPLUG; @@ -655,13 +653,11 @@ void usbh_task(void* param) //--------------------------------------------------------------------+ static inline uint8_t get_new_address(void) { - uint8_t addr; - for (addr=1; addr <= CFG_TUSB_HOST_DEVICE_MAX; addr++) + for (uint8_t addr=1; addr <= CFG_TUSB_HOST_DEVICE_MAX; addr++) { - if (_usbh_devices[addr].state == TUSB_DEVICE_STATE_UNPLUG) - break; + if (_usbh_devices[addr].state == TUSB_DEVICE_STATE_UNPLUG) return addr; } - return addr; + return CFG_TUSB_HOST_DEVICE_MAX; } static inline uint8_t get_configure_number_for_device(tusb_desc_device_t* dev_desc) -- cgit v1.3.1