嵌入式C#定义

嵌入式C#定义,c,arm,embedded,cmsis,C,Arm,Embedded,Cmsis,在embedded C中,我遇到了以下(以及更多类似的)示例: GPIOA_AHB_BASE是一个地址,它是前面定义的。这段代码到底是做什么的?我知道defines是预处理器的指令,因此它用define中给定的值替换所有实例。比如说, #define GPIOA_AHB GPIOA_AHB_BASE 将GPIOA_AHB替换为GPIOA_AHB_BASE已定义的任何值。我不明白第一个案例中发生了什么…问题中的信息无法说明全部细节,但是: 如果源代码包含GPIOA\u-AHB作为标识符,则

在embedded C中,我遇到了以下(以及更多类似的)示例:

GPIOA_AHB_BASE是一个地址,它是前面定义的。这段代码到底是做什么的?我知道defines是预处理器的指令,因此它用define中给定的值替换所有实例。比如说,

 #define GPIOA_AHB   GPIOA_AHB_BASE

将GPIOA_AHB替换为GPIOA_AHB_BASE已定义的任何值。我不明白第一个案例中发生了什么…

问题中的信息无法说明全部细节,但是:

  • 如果源代码包含
    GPIOA\u-AHB
    作为标识符,则最初将替换为
    ((GPIOA\u-AHB\u类型*)GPIOA\u-AHB\u基)
  • 接下来会发生什么取决于
    GPIOA_AHB_Type
    GPIOA_AHB_BASE
    本身是否为宏
  • 如果存在一个
    #define GPIOA_AHB_BASE 0x10000
    ,则该值将插入替换文本中。类似地,如果存在
    #define GPIOA_AHB_Type uint8_t
    ,则该值将插入替换文本,导致代码包含:

    ((uint8_t *)0x10000)
    
  • 该值可以取消引用,并且将发生实际引用GPIO总线和设备的内存读取


  • GPIOA_AHB
    的定义中,我可以得出结论,它用于引用
    GPIO/AHB
    设备的寄存器

    访问这些寄存器的符号是
    GPIOA\u AHB->some\u register


    如果您在第二种情况下定义了
    GPIOA_AHB
    ,那么它将只是一个普通数字。如果不先将其强制转换为描述该设备内寄存器偏移量的结构(
    GPIOA\u AHB\u Type
    ),或者手动添加该设备寄存器空间内每个寄存器的偏移量,则无法使用它引用寄存器。

    您可能会得到预处理的源代码格式(例如,使用类似于
    gcc-C-e yoursource.C>yoursource.i
    )谢谢!到第3点为止。我现在知道发生了什么。部分((uint8_t*)0x10000)仍然很模糊…这会返回存储在地址0x10000处的值,并将其转换为uint8\u t吗?在我展示的假设扩展中,您会有一个表达式,如:
    uint8\u t b=*GPIOA\u AHB;
    从该地址读取一个字节,或
    *GPIOA\u AHB=0x83;
    将一个字节写入该地址(您可以读取或写入的地址)是准确的;详细的机制取决于定义。如果
    GPIOA\u AHB\u类型
    是一个结构而不是简单的类型,那么您可以使用
    GPIOA\u AHB->member
    访问该结构的成员。主要的一点是,它将硬件指定的内存地址转换为C程序可以使用的内容。这是不可移植的e、 但是有效。更常见的是,这类宏的编写方式是:
    #define GPIOA_AHB(*(volatile uint8_t*)GPIOA_AHB_BASE)
    。这样您就不必取消引用,而是将寄存器视为任何其他变量。此外,该类型需要是volatile的,因为它是一个硬件内存位置。
    ((uint8_t *)0x10000)