【发布时间】:2017-04-02 05:36:36
【问题描述】:
我是内核编程的新手,现在尝试将一些值写入设备驱动程序中的 32 位 GPIO 寄存器。 I/O 是ioremap()-ed 到内存地址。问题是,我不知道writel()/writeb()/writew() 是如何将位写入地址的。
供应商文件说注册在0xE5200000。我必须写入的位是 [0:3] 位,其余 28 位([4:31] 位)为零。
这是我目前编写的设备驱动程序中的部分代码:
#define TCON_ADDR 0xE250000 // The address as provided by the vendor
static void *TIMER_CON_ADDR;
// I have to map and write to the address when the device is opened
static int on_dev_open(struct inode *inode, struct file *file) {
unsigned int data;
TIMER_CON_ADDR = ioremap(TCON_ADDR, 4); // Map the [0:4] bits to TIMER_CON_ADDR
data = 4; // 0100 in binary
writel(data, TIMER_CON_ADDR); // Write 0100 to TIMER_CON_ADDR
return 0;
}
上面的代码对你们来说可能是彻头彻尾的胡言乱语,但我不熟悉write(l|w|b)和ioremap()。
所以我的问题是:
- 我是否将
[0:4]位正确映射到TIMER_CON_ADDR? - 如果没有,我该如何正确映射它们?
- 正确映射 4 位后,如何使用任何
write(1|w|b)函数以正确的顺序将位 (0100) 写入 TIMER_CON_ADDR? -
write(l|w|b)在后台做了什么来写入位? - 我是否遗漏/弄错了任何信息?
提前感谢您的所有帮助。
【问题讨论】:
-
它是现有的驱动程序还是您正在从头开始创建一个?你的代码有很多问题:你错过了地址中的 0,你错过了
iounmap()电话。在驱动程序中,尽管使用相同的writel()、iomap()/iounmap()等,但上述所有操作都以完全不同的方式完成。 -
我正在为我从中国在线购买的一块板子从头开始创建一个驱动程序,以学习内核编程。事实上,我很难为内核空间函数和宏寻找“标准”文档。不过,我发现我一直在寻找的“文档”在源代码中。仍然没有掌握内核的内部工作原理(例如,在 iomap() 中指定映射地址的大小有什么意义?无论如何都会写一个完整的字节/字/长字等等),但我想我每次我尝试都会越来越近。
-
最好只为其他硬件寻找类似的驱动程序以获得线索。您正在尝试编程哪种硬件?
-
@0andriy 一个 pwm 调节的蜂鸣器
-
所以,基本上你需要在drivers/pwm/下查看。我怀疑这正是您所需要的,如果您共享硬件规格(数据表)的 URL 会更好。
标签: c linux-kernel kernel-module gpio ioremap