驱动:操作虚拟地址:ioremap来进行映射。
查看6410原理图LED SCH如下:
从上图可以看到,要使得LED点亮,需要使得nLEDx输出的电平为低电平,继续查看SCH,可以看到nLEDx连接到主核心板的GPM 引脚,如下所示:
所以要操作的工作有:
1.设置GPM0 - GPM3为输出引脚
2.点灯或者灭灯,对GPMDAT 进行操作即可。
3.使用ioremap和iounmap对物理地址进行映射和取消映射。
具体代码如下:
#include <linux/module.h> #include <linux/kernel.h> #include <linux/fs.h> #include <linux/init.h> #include <asm/uaccess.h> #include <linux/device.h> #include <asm/io.h> struct class *first_dev_class; struct device *first_dev; volatile unsigned long *gpmcon = NULL; volatile unsigned long *gpmdat = NULL; static int first_drv_open(struct inode *inode, struct file *file) //设备节点的相关操作函数 { printk("first_drv_open!!\n"); //设置gpio为输出引脚 *gpmcon &= ~(0x3 | 0x3 << 4 | 0x3 << 8 | 0x3 << 12); *gpmcon |= (0x1 | 0x1 << 4 | 0x1 << 8 | 0x1 << 12); return 0; } static int first_drv_read(struct file *filp, char __user *buff, size_t count, loff_t *offp) { printk("first_drv_read!!\n"); return 0; } ssize_t first_drv_write(struct file *filp, const char __user *buf, size_t len, loff_t *ppos) { printk("first_drv_write!!\n"); int val; copy_from_user(&val,buf,len); if(val == 1){ //点灯 *gpmdat &= ~(1 << 0 | 1 << 1 | 1 << 2 | 1 << 3); }else if(val == 0){ //灭灯 *gpmdat |= (1 << 0 | 1 << 1 | 1 << 2 | 1 << 3); } return sizeof(buf); } static struct file_operations first_drv_fops = { //填充file_operations结构体 .owner = THIS_MODULE, .open = first_drv_open, .read = first_drv_read, .write = first_drv_write, }; int major; static int __init first_drv_init(void)//入口函数 { printk("first_drv_init\n"); major = register_chrdev(0,"first_drv",&first_drv_fops);//告诉内核设备的操作,将first_drv_fops挂接到主设备为123的索引节点上从而让app可以找到 first_dev_class = class_create(THIS_MODULE,"first_class"); first_dev = device_create(first_dev_class,NULL,MKDEV(major,0),NULL,"shanl"); gpmcon = (volatile unsigned long *)ioremap(0x7F008820, 16);//地理地址转换为虚拟地址 gpmdat = gpmcon + 1; return 0; } static void __exit first_drv_exit(void) { printk("first_drv_exit\n"); device_destroy(first_dev_class,MKDEV(major,0)); class_destroy(first_dev_class); unregister_chrdev(major,"first_drv"); iounmap(0x7F008820); } module_init(first_drv_init);//入口修饰函数 module_exit(first_drv_exit); MODULE_LICENSE("GPL"); //证书
#include <stdio.h> #include <fcntl.h> int main(int argc , char **argv) { int fd ; int val; if(argc < 2){ printf("Usage : %s <on/off> \n",argv[0]); return -1; } if(!strcmp(argv[1],"on")){ val = 1; }else if(!strcmp(argv[1],"off")){ val = 0; } fd = open("/dev/shanl",O_RDWR); //打开设备节点/dev/shanl if(fd < 0){ printf("Can not open devices\n"); return -1; } write(fd,&val,4);//向设备节点做写操作 return 0; }