1.头文件
#ifndef __MYLED_H__
#define __MYLED_H__
#define PHY_LED1_MODER 0X50006000
#define PHY_LED1_ODR 0X50006014
#define PHY_LED1_RCC 0X50000A28
#define PHY_LED2_MODER 0x50007000
#define PHY_LED2_ODR 0x50007014
#define PHY_LED2_RCC 0X50000A28
#endif
2.功能函数
#include<linux/fs.h>
#include <linux/init.h>
#include <linux/module.h>
#include<linux/uaccess.h>
#include<linux/io.h>
#include"myled.h"
//延时函数
void delay_ms(int ms)
{
int i,j;
for(i=0; i<ms; i++)
for(j=0; j<1800; j++);
}
int major;//用于存放驱动的主设备号
char kbuf[128]={0};
unsigned int*vir_moder;
unsigned int*vir_odr;
unsigned int*vir_rcc;
unsigned int*vir_moder2;
unsigned int*vir_odr2;
unsigned int*vir_rcc2;
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 __user *ubuf, size_t size, loff_t *off)
{
int ret;//定义变量接收函数返回值
printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
//先判断size的大小是否大于内核kbuf的大小,如果比kbuf大,把size的数据修改 为kbuf的大小
if(size>sizeof(kbuf))
size=sizeof(kbuf);
//将kbuf的数据拷贝给用户空间
ret=copy_to_user(ubuf,kbuf,size);
if(ret)
{
printk("copy_to_user filed\n");
return -EIO;
}
return 0;
}
ssize_t mycdev_write(struct file *file, const char __user *ubuf, size_t size, loff_t *off)
{
int ret;//定义变量接收函数返回值
printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
//先判断size的大小是否大于内核kbuf的大小,如果比kbuf大,把size的数据修改 为kbuf的大小
if(size>sizeof(kbuf))
size=sizeof(kbuf);
//从用户空间拷贝数据
ret=copy_from_user(kbuf,ubuf,size);
if(ret)
{
printk("copy_from_user filed\n");
return -EIO;
}
if(kbuf[0]=='1')
{
while(1){
(*vir_odr) |= (1<<10);//输出高电平
delay_ms(1000);
(*vir_odr) &= (~(1<<10));
delay_ms(1000);
/*PF10 PE8*/
(*vir_odr2) |= (1<<10);
delay_ms(1000);
(*vir_odr2) &= (~(1<<10));
delay_ms(1000);
(*vir_odr) |= (1<<8);
delay_ms(1000);
(*vir_odr) &= (~(1<<8));
delay_ms(1000);
}
}
else if(kbuf[0]=='0')
{
(*vir_odr) &= (~(1<<10));//输出低电平
/*PF10 PE8*/
(*vir_odr2) &= (~(1<<10));
(*vir_odr) &= (~(1<<8));
}
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,"mycdev",&fops);
if(major<0)
{
printk("字符设备驱动注册失败\n");
return major;
}
printk("字符设备驱动注册成功,major=%d\n",major);
//进行LED1相关寄存器的映射
vir_moder=ioremap(PHY_LED1_MODER,4);
if(vir_moder==NULL)
{
printk("vir_moder ioremap failed\n");
return -ENOMEM;
}
vir_odr=ioremap(PHY_LED1_ODR,4);
if(vir_odr==NULL)
{
printk("vir_odr ioremap failed\n");
return -ENOMEM;
}
vir_rcc=ioremap(PHY_LED1_RCC,4);
if(vir_rcc==NULL)
{
printk("vir_rcc ioremap failed\n");
return -ENOMEM;
}
//进行LED2相关寄存器的映射
vir_moder2=ioremap(PHY_LED2_MODER,4);
if(vir_moder2==NULL)
{
printk("vir_moder2 ioremap failed\n");
return -ENOMEM;
}
vir_odr2=ioremap(PHY_LED2_ODR,4);
if(vir_odr2==NULL)
{
printk("vir_odr2 ioremap failed\n");
return -ENOMEM;
}
vir_rcc2=ioremap(PHY_LED2_RCC,4);
if(vir_rcc2==NULL)
{
printk("vir_rcc2 ioremap failed\n");
return -ENOMEM;
}
printk("相关寄存器物理地址映射成功\n");
//进行寄存器初始化
(*vir_rcc) |= (1<<4);//rcc使能
(*vir_moder) &=(~(3<<20));
(*vir_moder) |= (1<<20);//设置为输出模式
(*vir_odr) &= (~(1<<10));//输出低电平
/*PF10*/
(*vir_rcc2) |= (1<<5);
(*vir_moder2) &= (~(3<<20));
(*vir_moder2) |= (1<<20); //设置输出模式
(*vir_odr2) &= (~(1<<10)); //输出低电平
/*PE8*/
(*vir_moder) &= (~(3<<16));
(*vir_moder) |= (1<<16); //设置输出模式
(*vir_odr) &= (~(1<<8)); //设置为低电平
printk("相关寄存器初始化成功\n");
return 0;
}
//出口函数
static void __exit mycdev_exit(void)
{
//取消物理地址的映射
iounmap(vir_moder);
iounmap(vir_odr);
iounmap(vir_rcc);
iounmap(vir_moder2);
iounmap(vir_odr2);
iounmap(vir_rcc2);
//注销字符设备驱动
unregister_chrdev(major,"mycdev");
}
module_init(mycdev_init);
module_exit(mycdev_exit);
MODULE_LICENSE("GPL");
3.测试函数