本文共 2098 字,大约阅读时间需要 6 分钟。
对硬件进行操作涉及到硬件相关的寄存器,内核中与之相关的几个常用函数有:
原型:void *ioremap(unsigned long phys_addr, unsigned long size)头文件:功能:将物理地址映射到内核虚拟地址空间,便于访问。返回转换后的虚拟地址参数:phys_addr:要映射的物理地址 size:映射的长度,如4表示4个字节
原型:void writel(unsigned int value,volatile void _iomem *addr)头文件:功能:往映射后的物理地址写入32位数据参数:value:待写入的数据 addr:映射后的物理地址,是一个虚拟地址
原型:unsigned int readl(const volatile void _iomem *addr)头文件:功能:从映射后的物理地址读取32位数据参数:addr:映射后的物理地址,是一个虚拟地址
因此,内核函数对确切的物理地址读写数据需要配合使用ioremap()函数和writel(),readl()函数。地址映射和寄存器读写还有其它的方法,具体的可以查看硬件访问技术。
led内核模块代码:
#include#include #include #include #include #include "led.h"#define LEDCON 0x7f008800#define LEDDAT 0x7f008808unsigned int *led_config; unsigned int *led_data; struct cdev cdev;dev_t devno;int led_open(struct inode *node, struct file *filp){ led_config = ioremap(LEDCON,4); writel(0x11110000,led_config);/*完成led硬件初始化*/ led_data = ioremap(LEDDAT,4); return 0;}long led_ioctl(struct file *filp, unsigned int cmd, unsigned long arg){ switch (cmd) { case LED_ON: writel(0x00,led_data); return 0; case LED_OFF: writel(0xff,led_data); return 0; default: return -EINVAL; }}static struct file_operations led_fops ={ .open = led_open, .unlocked_ioctl = led_ioctl,};static int led_init(){ cdev_init(&cdev,&led_fops); alloc_chrdev_region(&devno, 0 , 1 , "myled"); cdev_add(&cdev, devno, 1); return 0; }static void led_exit(){ cdev_del(&cdev); unregister_chrdev_region(devno,1);}module_init(led_init);module_exit(led_exit);
应用程序代码:
#include#include #include #include #include "led.h"int main(int argc, char *argv[]){ int fd; int cmd; if (argc <2 ) { printf("please enter the second para!\n"); return 0; } cmd = atoi(argv[1]); fd = open("/dev/myled",O_RDWR); if (cmd == 1) ioctl(fd,LED_ON); else ioctl(fd,LED_OFF); return 0;}
转载地址:http://srigi.baihongyu.com/