我对内核编程很陌生,现在我试图在设备驱动程序中将一些值写入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?write(1|w|b)函数以正确的顺序将位(0100)写入TIMER_CON_ADDR?write(l|w|b)在引擎盖下做什么来写位呢?谢谢你提前提供帮助。
发布于 2017-04-02 08:22:32
[0:4]位映射到TIMER_CON_ADDR?不,你写32位,writel写4字节,4*8=32位
无法映射4位,最小8位=1字节,但是如果您使用32位寄存器,则需要map 32位=4字节。也不要忘记检查和处理错误。
write(1|w|b)函数以正确的顺序将位(0100)写入TIMER_CON_ADDR?您需要使用readl,内核中充满了示例,只需在linux内核源代码树的grep子目录中运行drivers。一般想法读/写:
u32 reg = readl(TIMER_CON_ADDR);
reg &= ~0xfu;
reg |= 4;
writel(reg, TIMER_CON_ADDR);write(l|w|b)在引擎盖下做什么来写位呢?看看源代码,它只是简单的C函数,比如:
static inline void __raw_writel(u32 value, volatile void __iomem *addr)
{
*(volatile u32 __force *)addr = value;
}主要的想法是告诉编译器,它不应该删除您的内存读写。
阅读类似驱动程序的源代码,它已经包含了此类简单驱动程序的几乎所有解决方案。
https://stackoverflow.com/questions/43164988
复制相似问题