AVR I/O 宏定义如何工作以允许访问寄存器?

Posted

技术标签:

【中文标题】AVR I/O 宏定义如何工作以允许访问寄存器?【英文标题】:How do AVR I/O macro definitions work to allow access to registers? 【发布时间】:2020-08-24 16:24:53 【问题描述】:

我正在查看 ATmega2560 寄存器映射 (iom2560.h) 的标头,其中包含所有寄存器的定义。例如:

#define PINA    _SFR_IO8(0X00)
//Macro definition:
#define _SFR_IO8(io_addr) ((io_addr) + 0X20)

所以 PINA 是一个 8 位十六进制值,对应 8 位微控制器寄存器的地址。当我编写代码时,只需键入以下代码即可更改寄存器中的值:

PINA |= (1 << 3); // Setting the third bit.

问题来了:为什么我可以通过将值分配给 PINA 来写入寄存器值(“由他的地址 _SFR_IO8(0X00) 指向”)?不是指向寄存器的地址吗?编译器是如何工作的?

非常感谢您

【问题讨论】:

问题中有:#define _SFR_IO8(io_addr) ((io_addr) + 0X20) 嗯,但这个定义看起来不正确,它应该确实是一个内存访问(在中间涉及另一个宏 _MMIO_BYTE,其中 确实 包含一个 * , 因为它的计算结果为 *(volatile uint8_t *)(addr)): electronics.stackexchange.com/a/463593/109961 - 我认为你忽略了 _SFR_IO8 定义中的 _MMIO_BYTE 部分! 感谢 CherryDT! - 实际上我两者都有 - 定义与标志 _SFR_ASM_COMPAT 有关。 是否定义了_SFR_ASM_COMPAT?因为这个定义在#if _SFR_ASM_COMPAT里面 "编译器是如何工作的?[原文如此]这个问题你可以自己回答,如果你真的想知道的话。gcc 是开源的。 【参考方案1】:

简短的回答 - 隐藏在 Atmel 包含的标头中的是一组宏,它们创建指向寄存器位置的指针。以下是该过程的简要概述:

您的 Makefile 定义要使用的设备,然后将定义传递给编译器。

DEVICE = atmega2560
...
-D__$(DEVICE)__

然后包含 io.h,它会根据您的设备自动包含必要的标头:

// In main source file
#include <io.h>    

// In io.h
#include <avr/sfr_defs.h>
// ...
#elif defined (__AVR_ATmega2560__)
    #  include <avr/iom2560.h>

// In sfr_defs.h
#define _MMIO_BYTE(mem_addr) (*(volatile uint8_t *)(mem_addr))
#define __SFR_OFFSET 0x20
#define _SFR_IO8(io_addr) _MMIO_BYTE((io_addr) + __SFR_OFFSET)

// In iom2560.h
#include <avr/iomxx0_1.h>
// Other device specific definitions

// Om iomxx0_1.h
#define PINA    _SFR_IO8(0X00)
// Other device family shared definitions

所以如果你展开所有这些,你得到的是一个指向寄存器地址的易失性指针。当您在代码中使用 PINA 时,预编译器会将其替换为所有扩展宏:

PINA
_SFR_IO8(0X00)
_MMIO_BYTE((0X00) + __SFR_OFFSET)
(*(volatile uint8_t *)((0X00) + 0x20))

其中指定 PINA 是指向 0x20 的易失性 8 位内存地址的指针。然后,每当访问该地址时,内部芯片架构都会将该地址映射到相应的外设寄存器。

【讨论】:

通过-save-temps参数avr-gcc你可以看到预处理后的C源代码(称为*.i)和编译后的汇编代码(称为*.s)来验证实际是什么在您的实际情况中进行。

以上是关于AVR I/O 宏定义如何工作以允许访问寄存器?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 C 宏定义 PIC 单片机引脚名称?

AVR--IO结构分析

为 I/O 中使用的寄存器的基地址寻找 INTEL 以太网设备相关宏的宏的内核头文件

LaTeX怎么实现的嵌套关系

了解 AVR 编程的 Subi 语法

如何在单独的 .asm 文件中定义子程序/宏?