⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 compiler.h

📁 FreeRTOS is a portable, open source, mini Real Time Kernel - a free to download and royalty free RTO
💻 H
📖 第 1 页 / 共 3 页
字号:
 * static storage duration, and like the corresponding assembly instructions
 * when applied to non-constant expressions (values unknown at compile time), so
 * they are more optimized than an assembly periphrasis. Hence, clz and ctz
 * ensure a possible and optimized behavior for both constant and non-constant
 * expressions.
 */
//! @{

/*! \brief Counts the leading zero bits of the given value considered as a 32-bit integer.
 *
 * \param u Value of which to count the leading zero bits.
 *
 * \return The count of leading zero bits in \a u.
 */
#if __GNUC__
  #define clz(u)              __builtin_clz(u)
#elif __ICCAVR32__
  #define clz(u)              __count_leading_zeros(u)
#endif

/*! \brief Counts the trailing zero bits of the given value considered as a 32-bit integer.
 *
 * \param u Value of which to count the trailing zero bits.
 *
 * \return The count of trailing zero bits in \a u.
 */
#if __GNUC__
  #define ctz(u)              __builtin_ctz(u)
#elif __ICCAVR32__
  #define ctz(u)              __count_trailing_zeros(u)
#endif

//! @}


/*! \name Alignment
 */
//! @{

/*! \brief Tests alignment of the number \a val with the \a n boundary.
 *
 * \param val Input value.
 * \param n   Boundary.
 *
 * \return \c 1 if the number \a val is aligned with the \a n boundary, else \c 0.
 */
#define Test_align(val, n     ) (!Tst_bits( val, (n) - 1     )   )

/*! \brief Gets alignment of the number \a val with respect to the \a n boundary.
 *
 * \param val Input value.
 * \param n   Boundary.
 *
 * \return Alignment of the number \a val with respect to the \a n boundary.
 */
#define Get_align( val, n     ) (  Rd_bits( val, (n) - 1     )   )

/*! \brief Sets alignment of the lvalue number \a lval to \a alg with respect to the \a n boundary.
 *
 * \param lval  Input/output lvalue.
 * \param n     Boundary.
 * \param alg   Alignment.
 *
 * \return New value of \a lval resulting from its alignment set to \a alg with respect to the \a n boundary.
 */
#define Set_align(lval, n, alg) (  Wr_bits(lval, (n) - 1, alg)   )

/*! \brief Aligns the number \a val with the upper \a n boundary.
 *
 * \param val Input value.
 * \param n   Boundary.
 *
 * \return Value resulting from the number \a val aligned with the upper \a n boundary.
 */
#define Align_up(  val, n     ) (((val) + ((n) - 1)) & ~((n) - 1))

/*! \brief Aligns the number \a val with the lower \a n boundary.
 *
 * \param val Input value.
 * \param n   Boundary.
 *
 * \return Value resulting from the number \a val aligned with the lower \a n boundary.
 */
#define Align_down(val, n     ) ( (val)              & ~((n) - 1))

//! @}


/*! \name Mathematics
 *
 * The same considerations as for clz and ctz apply here but AVR32-GCC does not
 * provide built-in functions to access the assembly instructions abs, min and
 * max and it does not produce them by itself in most cases, so two sets of
 * macros are defined here:
 *   - Abs, Min and Max to apply to constant expressions (values known at
 *     compile time);
 *   - abs, min and max to apply to non-constant expressions (values unknown at
 *     compile time).
 */
//! @{

/*! \brief Takes the absolute value of \a a.
 *
 * \param a Input value.
 *
 * \return Absolute value of \a a.
 *
 * \note More optimized if only used with values known at compile time.
 */
#define Abs(a)              (((a) <  0 ) ? -(a) : (a))

/*! \brief Takes the minimal value of \a a and \a b.
 *
 * \param a Input value.
 * \param b Input value.
 *
 * \return Minimal value of \a a and \a b.
 *
 * \note More optimized if only used with values known at compile time.
 */
#define Min(a, b)           (((a) < (b)) ?  (a) : (b))

/*! \brief Takes the maximal value of \a a and \a b.
 *
 * \param a Input value.
 * \param b Input value.
 *
 * \return Maximal value of \a a and \a b.
 *
 * \note More optimized if only used with values known at compile time.
 */
#define Max(a, b)           (((a) > (b)) ?  (a) : (b))

/*! \brief Takes the absolute value of \a a.
 *
 * \param a Input value.
 *
 * \return Absolute value of \a a.
 *
 * \note More optimized if only used with values unknown at compile time.
 */
#if __GNUC__
  #define abs(a) \
  (\
    {\
      int __value = (a);\
      __asm__ ("abs\t%0" : "+r" (__value) :  : "cc");\
      __value;\
    }\
  )
#elif __ICCAVR32__
  #define abs(a)      Abs(a)
#endif

/*! \brief Takes the minimal value of \a a and \a b.
 *
 * \param a Input value.
 * \param b Input value.
 *
 * \return Minimal value of \a a and \a b.
 *
 * \note More optimized if only used with values unknown at compile time.
 */
#if __GNUC__
  #define min(a, b) \
  (\
    {\
      int __value, __arg_a = (a), __arg_b = (b);\
      __asm__ ("min\t%0, %1, %2" : "=r" (__value) : "r" (__arg_a), "r" (__arg_b));\
      __value;\
    }\
  )
#elif __ICCAVR32__
  #define min(a, b)   __min(a, b)
#endif

/*! \brief Takes the maximal value of \a a and \a b.
 *
 * \param a Input value.
 * \param b Input value.
 *
 * \return Maximal value of \a a and \a b.
 *
 * \note More optimized if only used with values unknown at compile time.
 */
#if __GNUC__
  #define max(a, b) \
  (\
    {\
      int __value, __arg_a = (a), __arg_b = (b);\
      __asm__ ("max\t%0, %1, %2" : "=r" (__value) : "r" (__arg_a), "r" (__arg_b));\
      __value;\
    }\
  )
#elif __ICCAVR32__
  #define max(a, b)   __max(a, b)
#endif

//! @}


/*! \brief Calls the routine at address \a addr.
 *
 * It generates a long call opcode.
 *
 * For example, `Long_call(0x80000000)' generates a software reset on a UC3 if
 * it is invoked from the CPU supervisor mode.
 *
 * \param addr  Address of the routine to call.
 *
 * \note It may be used as a long jump opcode in some special cases.
 */
#define Long_call(addr)                   ((*(void (*)(void))(addr))())

/*! \brief Resets the CPU by software.
 *
 * \warning It shall not be called from the CPU application mode.
 */
#if __GNUC__
  #define Reset_CPU() \
  (\
    {\
      __asm__ __volatile__ (\
        "lddpc   r9, 3f\n\t"\
        "mfsr    r8, %[SR]\n\t"\
        "bfextu  r8, r8, %[SR_MX_OFFSET], %[SR_MX_SIZE]\n\t"\
        "cp.w    r8, 0b001\n\t"\
        "breq    0f\n\t"\
        "sub     r8, pc, $ - 1f\n\t"\
        "pushm   r8-r9\n\t"\
        "rete\n"\
        "0:\n\t"\
        "mtsr    %[SR], r9\n"\
        "1:\n\t"\
        "mov     r0, 0\n\t"\
        "mov     r1, 0\n\t"\
        "mov     r2, 0\n\t"\
        "mov     r3, 0\n\t"\
        "mov     r4, 0\n\t"\
        "mov     r5, 0\n\t"\
        "mov     r6, 0\n\t"\
        "mov     r7, 0\n\t"\
        "mov     r8, 0\n\t"\
        "mov     r9, 0\n\t"\
        "mov     r10, 0\n\t"\
        "mov     r11, 0\n\t"\
        "mov     r12, 0\n\t"\
        "mov     sp, 0\n\t"\
        "stdsp   sp[0], sp\n\t"\
        "ldmts   sp, sp\n\t"\
        "mov     lr, 0\n\t"\
        "lddpc   pc, 2f\n\t"\
        ".balign 4\n"\
        "2:\n\t"\
        ".word   _start\n"\
        "3:\n\t"\
        ".word   %[RESET_SR]"\
        :\
        : [SR] "i" (AVR32_SR),\
          [SR_MX_OFFSET] "i" (AVR32_SR_M0_OFFSET),\
          [SR_MX_SIZE] "i" (AVR32_SR_M0_SIZE + AVR32_SR_M1_SIZE + AVR32_SR_M2_SIZE),\
          [RESET_SR] "i" (AVR32_SR_GM_MASK | AVR32_SR_EM_MASK | AVR32_SR_M0_MASK)\
      );\
    }\
  )
#elif __ICCAVR32__
  #define Reset_CPU() \
  {\
    extern void *volatile __program_start;\
    __asm__ __volatile__ (\
      "mov     r7, LWRD(__program_start)\n\t"\
      "orh     r7, HWRD(__program_start)\n\t"\
      "mov     r9, LWRD("ASTRINGZ(AVR32_SR_GM_MASK | AVR32_SR_EM_MASK | AVR32_SR_M0_MASK)")\n\t"\
      "orh     r9, HWRD("ASTRINGZ(AVR32_SR_GM_MASK | AVR32_SR_EM_MASK | AVR32_SR_M0_MASK)")\n\t"\
      "mfsr    r8, "ASTRINGZ(AVR32_SR)"\n\t"\
      "bfextu  r8, r8, "ASTRINGZ(AVR32_SR_M0_OFFSET)", "ASTRINGZ(AVR32_SR_M0_SIZE + AVR32_SR_M1_SIZE + AVR32_SR_M2_SIZE)"\n\t"\
      "cp.w    r8, 001b\n\t"\
      "breq    $ + 10\n\t"\
      "sub     r8, pc, -12\n\t"\
      "pushm   r8-r9\n\t"\
      "rete\n\t"\
      "mtsr    "ASTRINGZ(AVR32_SR)", r9\n\t"\
      "mov     r0, 0\n\t"\
      "mov     r1, 0\n\t"\
      "mov     r2, 0\n\t"\
      "mov     r3, 0\n\t"\
      "mov     r4, 0\n\t"\
      "mov     r5, 0\n\t"\
      "mov     r6, 0\n\t"\
      "st.w    r0[4], r7\n\t"\
      "mov     r7, 0\n\t"\
      "mov     r8, 0\n\t"\
      "mov     r9, 0\n\t"\
      "mov     r10, 0\n\t"\
      "mov     r11, 0\n\t"\
      "mov     r12, 0\n\t"\
      "mov     sp, 0\n\t"\
      "stdsp   sp[0], sp\n\t"\
      "ldmts   sp, sp\n\t"\
      "mov     lr, 0\n\t"\
      "ld.w    pc, lr[4]"\
    );\
    __program_start;\
  }
#endif


/*! \name System Register Access
 */
//! @{

/*! \brief Gets the value of the \a sysreg system register.
 *
 * \param sysreg  Address of the system register of which to get the value.
 *
 * \return Value of the \a sysreg system register.
 */
#if __GNUC__
  #define Get_system_register(sysreg)         __builtin_mfsr(sysreg)
#elif __ICCAVR32__
  #define Get_system_register(sysreg)         __get_system_register(sysreg)
#endif

/*! \brief Sets the value of the \a sysreg system register to \a value.
 *
 * \param sysreg  Address of the system register of which to set the value.
 * \param value   Value to set the \a sysreg system register to.
 */
#if __GNUC__
  #define Set_system_register(sysreg, value)  __builtin_mtsr(sysreg, value)
#elif __ICCAVR32__
  #define Set_system_register(sysreg, value)  __set_system_register(sysreg, value)
#endif

//! @}


/*! \name CPU Status Register Access
 */
//! @{

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -