1

我能够使用 mmap 系统调用直接从用户空间控制 LED 操作来控制 GPIO。现在我想在内核空间中实现驱动程序。

我正在尝试为 ARM 控制器 RPi 在 Linux 中为 16*2 行 LCD 编写我的第一个内核空间设备驱动程序。现在我需要为此访问 GPIO。

在 AVR 中,我用这样的方式访问端口。

#define PORTA  *(volatile unsigned char*)0x30

我正在阅读 LLD,它告诉使用 inb() 和 outb() 函数来访问 i/o 端口。
http://www.makelinux.net/ldd3/chp-9-sect-2

1>我们可以不使用#define端口地址来访问GPIO吗?

2> 使用 inb() & outb() 函数来控制 GPIO 有什么好处?

请建议。

4

2 回答 2

1

在 AVR 中,我用这样的方式访问端口。

#define PORTA  *(volatile unsigned char*)0x30

这是一个不正确的定义,它使符号重载PORTA
除了将端口地址定义为 0x30 之外,您还取消了对该位置的引用。
所以它实际上是一个读取操作,但名称中没有说明,即您确实为READ_PORTA.

1>我们可以不使用#define端口地址来访问GPIO吗?

当然你可以(而且应该)。

 #define PORTA (unsigned char *)0x30

您会在 Linux 源代码树中的设备寄存器的头文件中找到类似的语句。在开发新的设备驱动程序时,我会为所有设备的寄存器和命令代码寻找一个头文件,#defines如果没有可用的文件,就开始编写一个。

2> 使用 inb() & outb() 函数来控制 GPIO 有什么好处?

代码是一个明确的 I/O 正在执行的声明,无论架构是使用 I/O 端口还是内存映射 I/O。
任何阅读以下内容的人都应该能够推断出发生了什么:

x = inb(PORTA);

与使用宏时的混乱相比:

x = PORTA;

上述使用重载宏的语句不会通过有能力的编码人员进行的代码审查。

您还应该熟悉并使用Linux 内核编码风格

于 2013-02-20T11:13:10.530 回答
0

1) 使用定义经常简化您的任务。当然,你可以不为你的端口使用define,而是在你需要访问端口的任何地方使用这个结构。但是,如果您更改设备的设计,例如,如果您决定将 LED 连接到端口 B,您将不得不用另一个地址替换任何地方的 0x30。此外,它会使您的代码可读性降低。或者,您可以声明一个将访问您的端口的函数。如果声明了这样一个简单的函数inline(如果您的编译器支持内联),则性能没有差异。

2)使用的优点inb()outb()你的程序的可移植性。如果这不是问题,那么直接访问您的端口就可以了。

于 2013-02-19T18:24:22.977 回答