了解#define预处理程序指令宏语法

时间:2019-07-03 12:01:56

标签: c pointers c-preprocessor lpc

以下代码摘自LPC54618.h头文件:

compile project(':react-native-pusher-push-notifications')
implementation 'com.google.firebase:firebase-core'
implementation 'com.google.firebase:firebase-messaging'
implementation 'com.pusher:push-notifications-android'
  1. 据我所知

    typedef struct { //...structure elements __IO uint32_t SDIOCLKSEL; //...more elements } SYSCON_Type; #define SYSCON_BASE (0x40000000u) #define SYSCON ((SYSCON_Type *)SYSCON_BASE)

我假设它创建了一个名为#define SYSCON ((SYSCON_Type *)SYSCON_BASE)的指针,该指针指向类型为SYSCON的变量,该变量存储在地址SYSCON_Type中。这真的发生了吗?并有任何资源说明此处使用的语法(即在宏内定义指针)吗?

  1. 当我尝试直接更改SDIOCLKSEL的值时,即:

    0x40000000u

    我得到一个错误:

    SYSCON->SDIOCLKSEL = some value;

但是如果我在函数中使用它,例如:

error: expected ')'
error: expected parameter declarator
error: expected ')'
error: expected function body after function declarator

没有错误。这是为什么?为什么我不能直接写结构?

任何答案将不胜感激!

2 个答案:

答案 0 :(得分:0)

这很容易。

  

它创建一个名为SYSCON的指针,该指针指向变量   类型SYSCON_Type,存储在地址0x40000000u中。这是   真的会发生什么?

是,不是。当您使用宏SYSCON

void foo(uint32_t value)
{
  ((SYSCON_Type *)0x40000000u)->SDIOCLKSEL = value;
}

预处理器转换为:

value

将32位无符号@PostMapping("/guardarproducto") public ResponseEntity<Usuario> insertProduct(@RequestBody String body, @RequestParam("imagen") MultipartFile imagen) { .... } 写入地址0x40000000u + struct成员偏移量的内存位置。

通常用于访问映射到内存地址空间中的硬件寄存器。

您需要在函数内部进行操作(就像所有C语言代码一样)

答案 1 :(得分:0)

#define SYSCON_BASE         (0x40000000u)

这只是在物理地址0x40000000上列出。

#define SYSCON ((SYSCON_Type *)SYSCON_BASE)

这通过转换将整数常量0x40000000u转换为指向struct的指针。它实际上并没有分配任何东西-实际的寄存器已经分配为内存映射的硬件。

简而言之,它说:“在地址0x40000000处有一个硬件外围设备SYSCON”(无论是什么计时器?)。常见的情况是,MCU内有多个相同类型的硬件外设(许多SPI,ADC等),每个外设具有相同的寄存器布局,但位于不同的地址。我们可以为每个此类外设使用相同的结构类型,也可以使用相同的驱动程序代码。

该结构本身将具有一个内存映射,它对应于寄存器布局的100%。在这里重要的是要确保填充/对齐不会搞砸,但希望MCU制造商已经想到了这一点(尽管不要认为这是理所当然的)。

假设SDIOCLKSEL的寄存器偏移为0x10,然后键入SYSCON->SDIOCLKSEL = some value;时,您将获得如下所示的机器代码(伪汇编代码):

LOAD 0x40000000 into index register X  
LOAD 0x10 into register A
ADD A to X
MOVE some value into the address of X

(ARM获得了可以根据偏移量进行移动的特殊指令,因此实际机器代码中的指令可能更少。后续的寄存器访问可以使“ X”保持不变,并重复使用该基地址来获得有效的代码。)

__IO限定词只是隐藏代码volatile的代码膨胀。

尝试“直接写入结构”时出现错误的原因仅仅是因为您无法在所有函数之外执行代码,而与该结构无关。