实现三盏灯的控制
mycdev.c
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/io.h>
#include "head.h"
int major;
char *devname = "mycdev";
char buf[128]={0};
unsigned int *rcc;//存放rcc的地址
unsigned int *pe_moder;//pe_moder的地址
unsigned int *pe_odr;
unsigned int *pf_moder;//pf的地址
unsigned int *pf_odr;
int mycdev_open(struct inode *inode,struct file *file)
{
printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
return 0;
}
ssize_t mycdev_read(struct file *file,char *ubuf,size_t size,loff_t *lof)
{
printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
long ref = copy_to_user(ubuf,buf,size);
if(ref)
{
printk("copy_to_user err\n");
return -EIO;
}
return 0;
}
ssize_t mycdev_write(struct file *file,const char *ubuf,size_t size,loff_t *lof)
{
printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
copy_from_user(buf,ubuf,size);
if(buf[0]==1)
{
*pe_odr ^= 1 << 10;//led1
}
else if(buf[0]==2)
{
*pf_odr ^= 1 << 10;//led2
}
else if(buf[0]==3)
{
*pe_odr ^= 1 << 8;//led3
}
return 0;
}
int mycdev_close(struct inode *inode,struct file *file)
{
printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
return 0;
}
struct file_operations fops = {
.open=mycdev_open,
.read=mycdev_read,
.write=mycdev_write,
.release=mycdev_close,
};
static int __init mycdev_init(void)
{
//注册
major = register_chrdev(0,devname,&fops);
if(major < 0)
{
printk("error\n");
return major;
}
printk("success major=%d\n",major);
//物理内存映射
rcc = ioremap(RCC,4);
if(!rcc)
{
printk("物理内存映射失败%d\n",__LINE__);
return -EFAULT;
}
pe_odr = ioremap(PE_ODR,4);
if(!pe_odr)
{
printk("物理内存映射失败%d\n",__LINE__);
return -EFAULT;
}
pe_moder = ioremap(PE_MODER,4);
if(!pe_moder)
{
printk("物理内存映射失败%d\n",__LINE__);
return -EFAULT;
}
pf_odr = ioremap(PF_ODR,4);
if(!pf_odr)
{
printk("物理内存映射失败%d\n",__LINE__);
return -EFAULT;
}
pf_moder = ioremap(PF_MODER,4);
if(!pf_moder)
{
printk("物理内存映射失败%d\n",__LINE__);
return -EFAULT;
}
//使能
*rcc |= 3 << 4;
*pe_moder &= ~(3 << 20);
*pe_moder |= 1 << 20;
*pe_moder &= ~(3 << 16);
*pe_moder |= 1 << 16;
*pf_moder &= ~(3 << 20);
*pf_moder |= 1 << 20;
return 0;
}
static void __exit mycdev_exit(void)
{
//取消物理内存映射
iounmap(rcc);
iounmap(pe_moder);
iounmap(pe_odr);
iounmap(pf_moder);
iounmap(pf_odr);
//取消注册
unregister_chrdev(0,devname);
}
module_init(mycdev_init);
module_exit(mycdev_exit);
MODULE_LICENSE("GPL");
head.h
#ifndef __HEAD_H__
#define __HEAD_H__
#define RCC 0x50000a28
#define PE_MODER 0x50006000
#define PE_ODR 0x50006014
#define PF_MODER 0x50007000
#define PF_ODR 0x50007014
#endif
test.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <strings.h>
int main()
{
char buf[128] = {0};
int fd = open("/dev/mycdev",O_RDWR);
if(fd<0)
{
printf("文件打开失败\n");
return -1;
}
while(1)
{
buf[0]=1;
write(fd,buf,sizeof(buf));
sleep(1);
buf[0]=1;
write(fd,buf,sizeof(buf));
sleep(1);
buf[0]=2;
write(fd,buf,sizeof(buf));
sleep(1);
buf[0]=2;
write(fd,buf,sizeof(buf));
sleep(1);
buf[0]=3;
write(fd,buf,sizeof(buf));
sleep(1);
buf[0]=3;
write(fd,buf,sizeof(buf));
sleep(1);
}
close(fd);
return 0;
}
本文介绍了如何在Linux系统中实现一个简单的字符设备驱动,控制三盏灯的开关,通过内存映射和文件操作进行通信。内容包括设备注册、内存映射、文件操作函数的编写以及主程序测试。
274

被折叠的 条评论
为什么被折叠?



