参考:https://wiki.sipeed.com/soft/Lichee/zh/Zero-Doc/Drive/GPIO_mmap.html
上一篇:荔枝派zero驱动开发03:设备树基础
下一篇:荔枝派zero驱动开发05:GPIO操作(使用GPIO子系统)
- 关键词:ioremap/iounmap,copy_from_user/copy_to_user,readl/writel
设备树修改:
本文不涉及设备树操作,但由于默认设备树配置了LED,因此先在设备树中禁用默认的LED配置,重新编译设备树后,使用新的设备树启动
关键代码:
#define V3S_GPIO_BASE 0x01C20800
// 模式寄存器,4bit,最高位保留,000输入,001为输出
#define V3S_GPIOG_MODE (V3S_GPIO_BASE + 0xD8)
// 每个脚的输入输出数据,1bit
#define V3S_GPIOG_DATA (V3S_GPIO_BASE + 0xE8)
static void __iomem *GPIOG_MODE;
static void __iomem *GPIOG_DATA;
GPIOG_MODE = ioremap(V3S_GPIOG_MODE, 4);
GPIOG_DATA = ioremap(V3S_GPIOG_DATA, 4);
uint32_t val=0;
val=readl(GPIOG_MODE);
val &= ~(7 << (PIN_N * 4)); // 清除配置
val |= (1 << (PIN_N * 4)); // 配置为输出
writel(val, GPIOG_MODE);
val=readl(GPIOG_DATA);
val &= ~(1 << PIN_N);
writel(val, GPIOG_DATA); // 引脚初始化为低
根据v3s寄存器表,GPIO的物理地址基址为0x01C20800,GPIOG的模式寄存器地址为(0x01C20800+0xD8)
在裸机开发中,可以直接读写*(0x01C20800+0xD8)来操作GPIO寄存器;但在linux中,内核不能直接访问物理地址,必须映射为虚拟地址后才可以访问,映射和取消映射的函数为ioremap()和iounmap()。
writel() 向内存映射的物理地址上写数据,wirtel() 写入 32 位数据 (4字节);readl同理,读取32位数据 (4字节);类似的操作函数有writeb/writew/writel,分别对应8位、16位、32位操作
位操作比较清晰,清除指定的位,或在指定位写入数据;v3s的模式寄存器每个脚占用4bit,