#include <linux/module.h>
#include <linux/init.h>
//包含必须的头文件#include <linux/fs.h>
#include <linux/miscdevice.h>
#include <asm/uaccess.h>
#include <asm/io.h>
//asm/io.h中定义, 用于把物理址映射 成虚拟地址,cookie--物理地址,size--虚拟地址,
//#define ioremap(cookie,size) __arm_ioremap((cookie), (size), MT_DEVICE)
unsigned long *base_addr = NULL; //存放物理地址对应的虚拟地址
//按照数据手册定义寄存器指针
#define BASE_ADDR (0x110002E0) //GPM4CON起始 地址
#define GPM4CON (*( volatile unsigned *)(base_addr+0))
#define GPM4DAT (*( volatile unsigned *)(base_addr+1))
//以下是文件操作方法的具体实现代码
static int xxx_open(struct inode *pinode, struct file *pfile )
{
printk(KERN_EMERG"file:%s\r\nline:%d, %s is call\n", __FILE__, __LINE__, __FUNCTION__);
//把 BASE_ADDR 物理地址映射成虚拟地址,大小为0x18
base_addr = (unsigned long *) ioremap(BASE_ADDR, 0x8);
GPM4CON &= ~0xffff; //清0
GPM4CON |= 0x1111; //配置为输出方向
GPM4DAT |= 0xf ; //配置为输出方向
return 0;
}
static int xxx_release (struct inode *pinode, struct file *pfile)
{
printk(KERN_EMERG"file:%s\r\nline:%d, %s is call\n", __FILE__, __LINE__, __FUNCTION__);
iounmap(base_addr); //释放映射后的虚拟地址空间
return 0;
}
//文件操作方法集合指针
static const struct file_operations mymisc_fops = {.open = xxx_open,
.release = xxx_release,
};
//定义核心结构
static struct miscdevice misc = {
.minor = 255,
.name = "myleds", ///dev目录下的设备名
.fops = &mymisc_fops,
};
static int __init mymisdevice_init(void)
{
int ret;
//注册核心结构
ret = misc_register(&misc);
if(ret < 0) {
printk(KERN_EMERG"misc_register error\n");
return ret;
}
printk(KERN_EMERG"misc_register ok\n");
return 0;
}
static void __exit mymisdevice_exit(void)
{
int ret;
//注销核心结构
ret = misc_deregister(&misc);
if(ret < 0) {
printk(KERN_EMERG"misc_deregister error\n");
return ;
}
printk(KERN_EMERG"misc_deregister ok\n");
}
module_init(mymisdevice_init);
module_exit(mymisdevice_exit);
MODULE_LICENSE("GPL");
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h> //lseek
#include <sys/ioctl.h> //ioctl
int fd; //存放文件描述符号
char save_buf[10]={0}; //存放数据使用
int main(void)
{
int ret;
int i;
//传递‘1’,‘0’表示对灯控制命令,‘1’表示灯亮, ‘0’表示灯灭
char t_buf[5] = {'1','0','1','0',0}; //要的灯状态是 亮灭亮灭
fd = open("/dev/myleds",O_RDWR); //以读写方式进行打开
if(fd < 0){
printf("open error\r\n");
return -1;
}
//写入4个灯控制状态:亮灭亮灭
write(fd,t_buf,4);
//回读当前的4个灯状态
read(fd,save_buf,4);
//判断读取回来的结果
for(i=0;i<4;i++)
{
if(save_buf[i] == '0')
printf("led %d off\n",i);
else if(save_buf[i] == '1')
printf("led %d on\n",i);
}
//关闭文件
close(fd);
return 0;
}
# Makefile 2.6
#hello是模块名,也是对应的c文件名。
obj-m += drv_leds.o
# KDIR 内核源码路径,根据自己需要设置
# X86 源码路径统一是/lib/modules/$(shell uname -r)/build
#如果要编译ARM的模块,则修改成ARM的内核源码路径
#KDIR :=/lib/modules/$(shell uname -r)/build
KDIR := /root/work/linux-3.5_xyd_modversion/
all:
@make -C $(KDIR) M=$(PWD) modules
@rm -rf .tmp_versions *.o *.mod.o *.mod.c *.bak *.symvers *.markers *.unsigned *.order *~ .*.*.cmd .*.*.*.cmd
arm-linux-gcc app.c -o app
cp app *.ko /root/work/rootfs/home
clean:
make -C $(KDIR) M=$(PWD) modules clean
@rm -rf app *.ko .tmp_versions *.o *.mod.o *.mod.c *.bak *.symvers *.markers *.unsigned *.order *~ .*.*.cmd .*.*.*.cmd