具体单板的按键驱动程序(查询方式)-以IMX6ull单板为例子
1.使能电源/时钟控制器
2.配置引脚模式
3.配置引脚方向–输入/输出
4.输出电平/读取电平
先看原理图确定引脚及其操作方法
◼ 平时按键电平为高,按下按键后电平为低。
◼ 按键引脚为 GPIO5_IO01、GPIO4_IO14。
再看芯片手册确定寄存器及其操作方法
第一步使能GPIO5
第二步使能GPIO4
第三步设置GPIO5_IO01,GPIO4_IO18为GPIO模式
第四步设置GPIO5_IO01,GPIO4_IO14为输入引脚,读取引脚电平
程序实现
button_test.c
#include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <stdio.h> #include <string.h> /* * ./button_test /dev/100ask_button0 * */ int main(int argc, char **argv) { int fd; char val; /* 1. 判断参数 */ if (argc != 2) { printf("Usage: %s <dev>\n", argv[0]); return -1; } /* 2. 打开文件 */ fd = open(argv[1], O_RDWR); if (fd == -1) { printf("can not open file %s\n", argv[1]); return -1; } /* 3. 写文件 */ read(fd, &val, 1); printf("get button : %d\n", val); close(fd); return 0; }
button_drv.h
#ifndef _BUTTON_DRV_H #define _BUTTON_DRV_H struct button_operations { int count; void (*init) (int which); int (*read) (int which); }; void register_button_operations(struct button_operations *opr); void unregister_button_operations(void); #endif
button_drv.c
#include <linux/module.h> #include <linux/errno.h> #include <linux/kernel.h> #include <linux/major.h> #include <linux/sched.h> #include <linux/slab.h> #include <linux/fcntl.h> #include <linux/fs.h> #include <linux/signal.h> #include <linux/mutex.h> #include <linux/mm.h> #include <linux/timer.h> #include <linux/wait.h> #include <linux/skbuff.h> #include <linux/proc_fs.h> #include <linux/poll.h> #include <linux/capi.h> #include <linux/kernelcapi.h> #include <linux/init.h> #include <linux/device.h> #include <linux/moduleparam.h> #include "button_drv.h" static int major = 0; static struct button_operations *p_button_opr; static struct class *button_class; static int button_open (struct inode *inode, struct file *file) { int minor = iminor(inode); p_button_opr->init(minor); return 0; } static ssize_t button_read (struct file *file, char __user *buf, size_t size, loff_t *off) { unsigned int minor = iminor(file_inode(file)); char level; int err; level = p_button_opr->read(minor); err = copy_to_user(buf, &level, 1); return 1; } static struct file_operations button_fops = { .open = button_open, .read = button_read, }; void register_button_operations(struct button_operations *opr) { int i; p_button_opr = opr; for (i = 0; i < opr->count; i++) { device_create(button_class, NULL, MKDEV(major, i), NULL, "100ask_button%d", i); } } void unregister_button_operations(void) { int i; for (i = 0; i < p_button_opr->count; i++) { device_destroy(button_class, MKDEV(major, i)); } } EXPORT_SYMBOL(register_button_operations); EXPORT_SYMBOL(unregister_button_operations); int button_init(void) { major = register_chrdev(0, "100ask_button", &button_fops); button_class = class_create(THIS_MODULE, "100ask_button"); if (IS_ERR(button_class)) return -1; return 0; } void button_exit(void) { class_destroy(button_class); unregister_chrdev(major, "100ask_button"); } module_init(button_init); module_exit(button_exit); MODULE_LICENSE("GPL");
board_100ask_imx6ull.c
#include <linux/module.h> #include <linux/fs.h> #include <linux/io.h> #include <linux/errno.h> #include <linux/miscdevice.h> #include <linux/kernel.h> #include <linux/major.h> #include <linux/mutex.h> #include <linux/proc_fs.h> #include <linux/seq_file.h> #include <linux/stat.h> #include <linux/init.h> #include <linux/device.h> #include <linux/tty.h> #include <linux/kmod.h> #include <linux/gfp.h> #include <asm/io.h> #include "button_drv.h" struct iomux { volatile unsigned int unnames[23]; volatile unsigned int IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO00; /* offset 0x5c */ volatile unsigned int IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO01; volatile unsigned int IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO02; volatile unsigned int IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03; volatile unsigned int IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO04; volatile unsigned int IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO05; volatile unsigned int IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO06; volatile unsigned int IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO07; volatile unsigned int IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO08; volatile unsigned int IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO09; volatile unsigned int IOMUXC_SW_MUX_CTL_PAD_UART1_TX_DATA; volatile unsigned int IOMUXC_SW_MUX_CTL_PAD_UART1_RX_DATA; volatile unsigned int IOMUXC_SW_MUX_CTL_PAD_UART1_CTS_B; }; struct imx6ull_gpio { volatile unsigned int dr; volatile unsigned int gdir; volatile unsigned int psr; volatile unsigned int icr1; volatile unsigned int icr2; volatile unsigned int imr; volatile unsigned int isr; volatile unsigned int edge_sel; }; /* enable GPIO4 */ static volatile unsigned int *CCM_CCGR3; /* enable GPIO5 */ static volatile unsigned int *CCM_CCGR1; /* set GPIO5_IO03 as GPIO */ static volatile unsigned int *IOMUXC_SNVS_SW_MUX_CTL_PAD_SNVS_TAMPER1; /* set GPIO4_IO14 as GPIO */ static volatile unsigned int *IOMUXC_SW_MUX_CTL_PAD_NAND_CE1_B; static struct iomux *iomux; static struct imx6ull_gpio *gpio4; static struct imx6ull_gpio *gpio5; static void board_imx6ull_button_init (int which) /* 初始化button, which-哪个button */ { if (!CCM_CCGR1) { CCM_CCGR1 = ioremap(0x20C406C, 4); CCM_CCGR3 = ioremap(0x20C4074, 4); IOMUXC_SNVS_SW_MUX_CTL_PAD_SNVS_TAMPER1 = ioremap(0x229000C, 4); IOMUXC_SW_MUX_CTL_PAD_NAND_CE1_B = ioremap(0x20E01B0, 4); iomux = ioremap(0x20e0000, sizeof(struct iomux)); gpio4 = ioremap(0x020A8000, sizeof(struct imx6ull_gpio)); gpio5 = ioremap(0x20AC000, sizeof(struct imx6ull_gpio)); } if (which == 0) { /* 1. enable GPIO5 * CG15, b[31:30] = 0b11 */ *CCM_CCGR1 |= (3<<30); /* 2. set GPIO5_IO01 as GPIO * MUX_MODE, b[3:0] = 0b101 */ *IOMUXC_SNVS_SW_MUX_CTL_PAD_SNVS_TAMPER1 = 5; /* 3. set GPIO5_IO01 as input * GPIO5 GDIR, b[1] = 0b0 */ gpio5->gdir &= ~(1<<1); } else if(which == 1) { /* 1. enable GPIO4 * CG6, b[13:12] = 0b11 */ *CCM_CCGR3 |= (3<<12); /* 2. set GPIO4_IO14 as GPIO * MUX_MODE, b[3:0] = 0b101 */ IOMUXC_SW_MUX_CTL_PAD_NAND_CE1_B = 5; /* 3. set GPIO4_IO14 as input * GPIO4 GDIR, b[14] = 0b0 */ gpio4->gdir &= ~(1<<14); } } static int board_imx6ull_button_read (int which) /* 读button, which-哪个 */ { //printk("%s %s line %d, button %d, 0x%x\n", __FILE__, __FUNCTION__, __LINE__, which, *GPIO1_DATAIN); if (which == 0) return (gpio5->psr & (1<<1)) ? 1 : 0; else return (gpio4->psr & (1<<14)) ? 1 : 0; } static struct button_operations my_buttons_ops = { .count = 2, .init = board_imx6ull_button_init, .read = board_imx6ull_button_read, }; int board_imx6ull_button_drv_init(void) { register_button_operations(&my_buttons_ops); return 0; } void board_imx6ull_button_drv_exit(void) { unregister_button_operations(); } module_init(board_imx6ull_button_drv_init); module_exit(board_imx6ull_button_drv_exit); MODULE_LICENSE("GPL");
上面涉及的就是一些对硬件的操作