编码风格-linux中的第一个内核空间驱动程序



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

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

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

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

我在读LLD,它告诉使用in()&out()函数访问i/o端口。
http://www.makelinux.net/ldd3/chp-9-sect-2

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

2> 使用in()&out()函数来控制GPIO?

请提出建议。

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

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

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

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

你当然可以(也应该)。

 #define PORTA (unsigned char *)0x30

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

2> 使用in()&out()函数来控制GPIO?

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

x = inb(PORTA);

与使用宏时的混乱:

x = PORTA;

使用重载宏的上述语句将无法通过主管编码人员进行的代码审查。

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

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

2) 使用CCD_ 5和CCD_ 6的优点是程序的可移植性。如果这不是问题,那么可以直接访问您的端口。

最新更新