首页 > 解决方案 > ARM 是否假设所有 Cortex-M 微控制器都是小端的?

问题描述

我目前正在从 SVD 文件生成 C++ 代码

在研究我对 ARM 应用程序二进制接口中位域布局的假设时,我遇到了ARM 的 Cortex-M7 内核的官方 C 头文件(在撰写本文时提交10a6d292f2)。

它包含以下代码:

/**
  \brief  Union type to access the Application Program Status Register (APSR).
 */
typedef union
{
  struct
  {
    uint32_t _reserved0:16;              /*!< bit:  0..15  Reserved */
    uint32_t GE:4;                       /*!< bit: 16..19  Greater than or Equal flags */
    uint32_t _reserved1:7;               /*!< bit: 20..26  Reserved */
    uint32_t Q:1;                        /*!< bit:     27  Saturation condition flag */
    uint32_t V:1;                        /*!< bit:     28  Overflow condition code flag */
    uint32_t C:1;                        /*!< bit:     29  Carry condition code flag */
    uint32_t Z:1;                        /*!< bit:     30  Zero condition code flag */
    uint32_t N:1;                        /*!< bit:     31  Negative condition code flag */
  } b;                                   /*!< Structure used for bit  access */
  uint32_t w;                            /*!< Type      used for word access */
} APSR_Type;

/* APSR Register Definitions */
#define APSR_N_Pos                         31U                                            /*!< APSR: N Position */
#define APSR_N_Msk                         (1UL << APSR_N_Pos)                            /*!< APSR: N Mask */

我故意在联合之后包含第一位掩码,因为它确认了ARM®v7-M 架构参考手册指定的内容:N 位,也称为“负条件代码标志”,始终是该寄存器的最高有效位,无论字节序。从相应位字段的注释中也可以清楚地看到这一点。

ARM 可能假设为 Cortex-M7 目标编译该代码的任何编译器都满足Arm® 架构的过程调用标准,这似乎是一个合理的假设。

该 ABI 指定(除其他外):

一系列位域按照声明的顺序排列 [...]。

这意味着struct上面的位域 N 将始终布置为内存中寄存器的最后一位。

然而,如果处理器是大端的,那么struct上面的位域 N 在这种情况下将是寄存器的最低有效位,即位 0,而不是位 31!

我在core_cm7.h中既没有发现注释也没有任何编译时标志可以解决这个问题。

事实上,我刚刚发现了另一段似乎证实了我的分析的 ARM 代码:

#ifndef __BIG_ENDIAN // bitfield layout of APSR is sensitive to endianness
typedef union
{
    struct
    {
        int mode:5;
        int T:1;
        int F:1;
        int I:1;
        int _dnm:19;
        int Q:1;
        int V:1;
        int C:1;
        int Z:1;
        int N:1;
    } b;
    unsigned int word;
} PSR;
#else /* __BIG_ENDIAN */
typedef union
{
    struct 
    {
        int N:1;
        int Z:1;
        int C:1;
        int V:1;
        int Q:1;
        int _dnm:19;
        int I:1;
        int F:1;
        int T:1;
        int mode:5;
    } b;
    unsigned int word;
} PSR;
#endif /* __BIG_ENDIAN */

这显然是针对不同的内核(我猜不是 Cortex),但它证实了这一原则。

那么 ARM 是否只是假设永远不会有任何大端 Cortex-M 处理器,还是我错过了什么?

标签: carmbitendiannesscortex-m

解决方案


我刚刚在 Github 上的 ARM CMSIS 存储库上注册了一个问题。我现在的假设是答案是肯定的:ARM 确实假设所有的 Cortex-M MCU 都是并且将是小端,至少在他们发布的代码中。我希望我能以某种方式从他们那里得到一些确认。在这种情况下,我会在这里发布。

编辑:

我的上述假设已被我注册问题的答案之一清楚地证实了。这要么是一种忽视,要么是一种无证的有意识的选择,但结果是一样的。

重申用于内存映射寄存器的显而易见的位字段:

  • 应该非常清楚地记录在案。在 C 和 C++ 中,它们使用实现定义的行为,因此只能在特定的 ABI 下才有意义。应明确规定此类代码预期工作的假设。
  • 假设一定的字节顺序。这在 ARM ABI 下是正确的,但可能是一个更普遍的问题。这意味着这样的代码需要有一个策略来断言字节顺序假设是正确的。

推荐阅读