c - 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 处理器,还是我错过了什么?
解决方案
我刚刚在 Github 上的 ARM CMSIS 存储库上注册了一个问题。我现在的假设是答案是肯定的:ARM 确实假设所有的 Cortex-M MCU 都是并且将是小端,至少在他们发布的代码中。我希望我能以某种方式从他们那里得到一些确认。在这种情况下,我会在这里发布。
编辑:
我的上述假设已被我注册问题的答案之一清楚地证实了。这要么是一种忽视,要么是一种无证的有意识的选择,但结果是一样的。
重申用于内存映射寄存器的显而易见的位字段:
- 应该非常清楚地记录在案。在 C 和 C++ 中,它们使用实现定义的行为,因此只能在特定的 ABI 下才有意义。应明确规定此类代码预期工作的假设。
- 假设一定的字节顺序。这在 ARM ABI 下是正确的,但可能是一个更普遍的问题。这意味着这样的代码需要有一个策略来断言字节顺序假设是正确的。
推荐阅读
- php - 在 PHP 中解析嵌套的 JSON
- javascript - 匹配正则表达式模式后的Javascript拆分,保留模式
- c++ - 为什么这段代码给了我垃圾值?
- .net-core - 连接到 Power BI 服务 .NetCore Database.Model 的 Azure 分析服务表格模型为空异常
- r - 缺少 KableOne 的空格(包“TableOne)
- reactjs - 添加firebase crashlytics后,React Native App卡在启动屏幕上?
- security - 使用 mmap 共享内存
- java - 在 Android Studio 项目中将 Java 双数组传递给 C++
- ffmpeg - FFMPEG - 裁剪图像,使图像的高度和宽度相等
- bots - webhook 处于活动状态时无法使用 getUpdates 方法;使用 deleteWebhook 先删除 webhook (DELETEWEBHOOK DOESN'T WORK)