add tu_unaligned_read32/write32 (#772)

* add tu_unaligned_read32/write32
* added tu_unaligned_read16/write16
* add TU_ATTR_ALWAYS_INLINE, add to most of simple inline function
This commit is contained in:
Ha Thach 2021-04-06 19:32:01 +07:00 committed by GitHub
parent ab4d30fd6b
commit 1d20c84798
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 91 additions and 46 deletions

View File

@ -76,51 +76,55 @@
#include "tusb_timeout.h" #include "tusb_timeout.h"
#include "tusb_types.h" #include "tusb_types.h"
//--------------------------------------------------------------------+ //------------- Mem -------------//
// Inline Functions
//--------------------------------------------------------------------+
#define tu_memclr(buffer, size) memset((buffer), 0, (size)) #define tu_memclr(buffer, size) memset((buffer), 0, (size))
#define tu_varclr(_var) tu_memclr(_var, sizeof(*(_var))) #define tu_varclr(_var) tu_memclr(_var, sizeof(*(_var)))
static inline uint32_t tu_u32(uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4) //------------- Bytes -------------//
TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_u32(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; return ( ((uint32_t) b1) << 24) | ( ((uint32_t) b2) << 16) | ( ((uint32_t) b3) << 8) | b4;
} }
static inline uint16_t tu_u16(uint8_t high, uint8_t low) TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_u16(uint8_t high, uint8_t low)
{ {
return (uint16_t)((((uint16_t) high) << 8) + low); return (uint16_t) ((((uint16_t) high) << 8) | low);
} }
static inline uint8_t tu_u16_high(uint16_t u16) { return (uint8_t) (((uint16_t) (u16 >> 8)) & 0x00ff); } TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_u16_high(uint16_t u16) { return (uint8_t) (((uint16_t) (u16 >> 8)) & 0x00ff); }
static inline uint8_t tu_u16_low (uint16_t u16) { return (uint8_t) (u16 & 0x00ff); } TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_u16_low (uint16_t u16) { return (uint8_t) (u16 & 0x00ff); }
// Min //------------- Bits -------------//
static inline uint8_t tu_min8 (uint8_t x, uint8_t y ) { return (x < y) ? x : y; } TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_bit_set (uint32_t value, uint8_t pos) { return value | TU_BIT(pos); }
static inline uint16_t tu_min16 (uint16_t x, uint16_t y) { return (x < y) ? x : y; } TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_bit_clear(uint32_t value, uint8_t pos) { return value & (~TU_BIT(pos)); }
static inline uint32_t tu_min32 (uint32_t x, uint32_t y) { return (x < y) ? x : y; } TU_ATTR_ALWAYS_INLINE static inline bool tu_bit_test (uint32_t value, uint8_t pos) { return (value & TU_BIT(pos)) ? true : false; }
// Max //------------- Min -------------//
static inline uint8_t tu_max8 (uint8_t x, uint8_t y ) { return (x > y) ? x : y; } TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_min8 (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; } TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_min16 (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; } TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_min32 (uint32_t x, uint32_t y) { return (x < y) ? x : y; }
// Align //------------- Max -------------//
static inline uint32_t tu_align(uint32_t value, uint32_t alignment) TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_max8 (uint8_t x, uint8_t y ) { return (x > y) ? x : y; }
TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_max16 (uint16_t x, uint16_t y) { return (x > y) ? x : y; }
TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_max32 (uint32_t x, uint32_t y) { return (x > y) ? x : y; }
//------------- Align -------------//
TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_align(uint32_t value, uint32_t alignment)
{ {
return value & ((uint32_t) ~(alignment-1)); return value & ((uint32_t) ~(alignment-1));
} }
static inline uint32_t tu_align32 (uint32_t value) { return (value & 0xFFFFFFE0UL); } TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_align32 (uint32_t value) { return (value & 0xFFFFFFE0UL); }
static inline uint32_t tu_align16 (uint32_t value) { return (value & 0xFFFFFFF0UL); } TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_align16 (uint32_t value) { return (value & 0xFFFFFFF0UL); }
static inline uint32_t tu_align4k (uint32_t value) { return (value & 0xFFFFF000UL); } TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_align4k (uint32_t value) { return (value & 0xFFFFF000UL); }
static inline uint32_t tu_offset4k(uint32_t value) { return (value & 0xFFFUL); } TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_offset4k(uint32_t value) { return (value & 0xFFFUL); }
//------------- Mathematics -------------// //------------- Mathematics -------------//
static inline uint32_t tu_abs(int32_t value) { return (uint32_t)((value < 0) ? (-value) : value); } TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_abs(int32_t value) { return (uint32_t)((value < 0) ? (-value) : value); }
/// inclusive range checking /// inclusive range checking TODO remove
static inline bool tu_within(uint32_t lower, uint32_t value, uint32_t upper) TU_ATTR_ALWAYS_INLINE static inline bool tu_within(uint32_t lower, uint32_t value, uint32_t upper)
{ {
return (lower <= value) && (value <= upper); return (lower <= value) && (value <= upper);
} }
@ -130,18 +134,49 @@ static inline bool tu_within(uint32_t lower, uint32_t value, uint32_t upper)
static inline uint8_t tu_log2(uint32_t value) static inline uint8_t tu_log2(uint32_t value)
{ {
uint8_t result = 0; uint8_t result = 0;
while (value >>= 1) { result++; }
while (value >>= 1)
{
result++;
}
return result; return result;
} }
// Bit //------------- Unaligned Access -------------//
static inline uint32_t tu_bit_set (uint32_t value, uint8_t pos) { return value | TU_BIT(pos); } #if TUP_ARCH_STRICT_ALIGN
static inline uint32_t tu_bit_clear(uint32_t value, uint8_t pos) { return value & (~TU_BIT(pos)); }
static inline bool tu_bit_test (uint32_t value, uint8_t pos) { return (value & TU_BIT(pos)) ? true : false; } typedef struct { uint16_t val; } TU_ATTR_PACKED tu_unaligned_uint16_t;
typedef struct { uint32_t val; } TU_ATTR_PACKED tu_unaligned_uint32_t;
TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_unaligned_read32(const void* mem)
{
tu_unaligned_uint32_t const* ua32 = (tu_unaligned_uint32_t const*) mem;
return ua32->val;
}
TU_ATTR_ALWAYS_INLINE static inline void tu_unaligned_write32(void* mem, uint32_t value)
{
tu_unaligned_uint32_t* ua32 = (tu_unaligned_uint32_t*) mem;
ua32->val = value;
}
TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_unaligned_read16(const void* mem)
{
tu_unaligned_uint16_t const* ua16 = (tu_unaligned_uint16_t const*) mem;
return ua16->val;
}
TU_ATTR_ALWAYS_INLINE static inline void tu_unaligned_write16(void* mem, uint16_t value)
{
tu_unaligned_uint16_t* ua16 = (tu_unaligned_uint16_t*) mem;
ua16->val = value;
}
#else
TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_unaligned_read32 (const void* mem ) { return *((uint32_t*) mem); }
TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_unaligned_read16 (const void* mem ) { return *((uint16_t*) mem); }
TU_ATTR_ALWAYS_INLINE static inline void tu_unaligned_write32 (void* mem, uint32_t value ) { *((uint32_t*) mem) = value; }
TU_ATTR_ALWAYS_INLINE static inline void tu_unaligned_write16 (void* mem, uint16_t value ) { *((uint16_t*) mem) = value; }
#endif
/*------------------------------------------------------------------*/ /*------------------------------------------------------------------*/
/* Count number of arguments of __VA_ARGS__ /* Count number of arguments of __VA_ARGS__
@ -153,9 +188,9 @@ static inline bool tu_bit_test (uint32_t value, uint8_t pos) { return (value
*------------------------------------------------------------------*/ *------------------------------------------------------------------*/
#ifndef TU_ARGS_NUM #ifndef TU_ARGS_NUM
#define TU_ARGS_NUM(...) NARG_(_0, ##__VA_ARGS__,_RSEQ_N()) #define TU_ARGS_NUM(...) _TU_NARG(_0, ##__VA_ARGS__,_RSEQ_N())
#define NARG_(...) _GET_NTH_ARG(__VA_ARGS__) #define _TU_NARG(...) _GET_NTH_ARG(__VA_ARGS__)
#define _GET_NTH_ARG( \ #define _GET_NTH_ARG( \
_1, _2, _3, _4, _5, _6, _7, _8, _9,_10, \ _1, _2, _3, _4, _5, _6, _7, _8, _9,_10, \
_11,_12,_13,_14,_15,_16,_17,_18,_19,_20, \ _11,_12,_13,_14,_15,_16,_17,_18,_19,_20, \

View File

@ -61,12 +61,14 @@
//--------------------------------------------------------------------+ //--------------------------------------------------------------------+
// Compiler porting with Attribute and Endian // Compiler porting with Attribute and Endian
//--------------------------------------------------------------------+ //--------------------------------------------------------------------+
// TODO refactor since __attribute__ is supported across many compiler
#if defined(__GNUC__) #if defined(__GNUC__)
#define TU_ATTR_ALIGNED(Bytes) __attribute__ ((aligned(Bytes))) #define TU_ATTR_ALIGNED(Bytes) __attribute__ ((aligned(Bytes)))
#define TU_ATTR_SECTION(sec_name) __attribute__ ((section(#sec_name))) #define TU_ATTR_SECTION(sec_name) __attribute__ ((section(#sec_name)))
#define TU_ATTR_PACKED __attribute__ ((packed)) #define TU_ATTR_PACKED __attribute__ ((packed))
#define TU_ATTR_PREPACKED
#define TU_ATTR_WEAK __attribute__ ((weak)) #define TU_ATTR_WEAK __attribute__ ((weak))
#define TU_ATTR_ALWAYS_INLINE __attribute__ ((always_inline))
#define TU_ATTR_DEPRECATED(mess) __attribute__ ((deprecated(mess))) // warn if function with this attribute is used #define TU_ATTR_DEPRECATED(mess) __attribute__ ((deprecated(mess))) // warn if function with this attribute is used
#define TU_ATTR_UNUSED __attribute__ ((unused)) // Function/Variable is meant to be possibly unused #define TU_ATTR_UNUSED __attribute__ ((unused)) // Function/Variable is meant to be possibly unused
#define TU_ATTR_USED __attribute__ ((used)) // Function/Variable is meant to be used #define TU_ATTR_USED __attribute__ ((used)) // Function/Variable is meant to be used
@ -85,8 +87,8 @@
#define TU_ATTR_ALIGNED(Bytes) __attribute__ ((aligned(Bytes))) #define TU_ATTR_ALIGNED(Bytes) __attribute__ ((aligned(Bytes)))
#define TU_ATTR_SECTION(sec_name) __attribute__ ((section(#sec_name))) #define TU_ATTR_SECTION(sec_name) __attribute__ ((section(#sec_name)))
#define TU_ATTR_PACKED __attribute__ ((packed)) #define TU_ATTR_PACKED __attribute__ ((packed))
#define TU_ATTR_PREPACKED
#define TU_ATTR_WEAK __attribute__ ((weak)) #define TU_ATTR_WEAK __attribute__ ((weak))
#define TU_ATTR_ALWAYS_INLINE __attribute__ ((always_inline))
#define TU_ATTR_DEPRECATED(mess) __attribute__ ((deprecated(mess))) // warn if function with this attribute is used #define TU_ATTR_DEPRECATED(mess) __attribute__ ((deprecated(mess))) // warn if function with this attribute is used
#define TU_ATTR_UNUSED __attribute__ ((unused)) // Function/Variable is meant to be possibly unused #define TU_ATTR_UNUSED __attribute__ ((unused)) // Function/Variable is meant to be possibly unused
#define TU_ATTR_USED __attribute__ ((used)) #define TU_ATTR_USED __attribute__ ((used))
@ -106,8 +108,8 @@
#define TU_ATTR_ALIGNED(Bytes) __attribute__ ((aligned(Bytes))) #define TU_ATTR_ALIGNED(Bytes) __attribute__ ((aligned(Bytes)))
#define TU_ATTR_SECTION(sec_name) __attribute__ ((section(#sec_name))) #define TU_ATTR_SECTION(sec_name) __attribute__ ((section(#sec_name)))
#define TU_ATTR_PACKED __attribute__ ((packed)) #define TU_ATTR_PACKED __attribute__ ((packed))
#define TU_ATTR_PREPACKED
#define TU_ATTR_WEAK __attribute__ ((weak)) #define TU_ATTR_WEAK __attribute__ ((weak))
#define TU_ATTR_ALWAYS_INLINE __attribute__ ((always_inline))
#define TU_ATTR_DEPRECATED(mess) __attribute__ ((deprecated(mess))) // warn if function with this attribute is used #define TU_ATTR_DEPRECATED(mess) __attribute__ ((deprecated(mess))) // warn if function with this attribute is used
#define TU_ATTR_UNUSED __attribute__ ((unused)) // Function/Variable is meant to be possibly unused #define TU_ATTR_UNUSED __attribute__ ((unused)) // Function/Variable is meant to be possibly unused
#define TU_ATTR_USED __attribute__ ((used)) // Function/Variable is meant to be used #define TU_ATTR_USED __attribute__ ((used)) // Function/Variable is meant to be used

View File

@ -36,7 +36,6 @@
* as C++ for the sake of code simplicity. Beware of a headache macro * as C++ for the sake of code simplicity. Beware of a headache macro
* manipulation that you are told to stay away. * manipulation that you are told to stay away.
* *
*
* This contains macros for both VERIFY and ASSERT: * This contains macros for both VERIFY and ASSERT:
* *
* VERIFY: Used when there is an error condition which is not the * VERIFY: Used when there is an error condition which is not the
@ -50,9 +49,8 @@
* quickly. One example would be adding assertions in library * quickly. One example would be adding assertions in library
* function calls to confirm a function's (untainted) * function calls to confirm a function's (untainted)
* parameters are valid. * parameters are valid.
*
* *
* The difference in behaviour is that ASSERT triggers a breakpoint while * The difference in behavior is that ASSERT triggers a breakpoint while
* verify does not. * verify does not.
* *
* #define TU_VERIFY(cond) if(cond) return false; * #define TU_VERIFY(cond) if(cond) return false;

View File

@ -124,7 +124,6 @@
#define OPT_OS_RTTHREAD 6 ///< RT-Thread #define OPT_OS_RTTHREAD 6 ///< RT-Thread
/** @} */ /** @} */
// Allow to use command line to change the config name/location // Allow to use command line to change the config name/location
#ifdef CFG_TUSB_CONFIG_FILE #ifdef CFG_TUSB_CONFIG_FILE
#include CFG_TUSB_CONFIG_FILE #include CFG_TUSB_CONFIG_FILE
@ -132,8 +131,6 @@
#include "tusb_config.h" #include "tusb_config.h"
#endif #endif
/** \addtogroup group_configuration /** \addtogroup group_configuration
* @{ */ * @{ */
@ -277,6 +274,19 @@
//------------- CLASS -------------// //------------- CLASS -------------//
#endif // TUSB_OPT_HOST_ENABLED #endif // TUSB_OPT_HOST_ENABLED
//--------------------------------------------------------------------+
// Port Options
// TUP for TinyUSB Port (can be renamed)
//--------------------------------------------------------------------+
// TUP_ARCH_STRICT_ALIGN if arch cannot access unaligned memory
// ARMv7+ (M3-M7, M23-M33) can access unaligned memory
#if (defined(__ARM_ARCH) && (__ARM_ARCH >= 7))
#define TUP_ARCH_STRICT_ALIGN 0
#else
#define TUP_ARCH_STRICT_ALIGN 1
#endif
//------------------------------------------------------------------ //------------------------------------------------------------------
// Configuration Validation // Configuration Validation