头文件:
#ifndef __LED_H__
#define __LED_H__
#define PHY_GPIOE 0x50006000
#define PHY_GPIOF 0x50007000
#define PHY_RCC 0x50000A28
typedef struct{
volatile unsigned int MODER;
volatile unsigned int OTYPER;
volatile unsigned int OSPEEDR;
volatile unsigned int PUPDR;
volatile unsigned int IDR;
volatile unsigned int ODR;
}gpio_t;
#endif
源文件:
#include
#include
#include
#include
#include
#include "myled.h"
#define CNAME "myled"
int major;
char kbuf[128]={0};
volatile unsigned int* RCC;
volatile gpio_t* GPIOE;
volatile gpio_t* GPIOF;
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 *loffs)
{
int res;
printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
//校验传输数据大小,如果用户空间传输数据的大小大于内核空间,需要更正传输数据大小
if(size>sizeof(kbuf)) size=sizeof(kbuf);
res=copy_to_user(kbuf,ubuf,size);
if(res)
{
printk("copy to user is error\n");
return -EIO;
}
return size;
}
ssize_t mycdev_write(struct file *file,const char __user *ubuf,size_t size,loff_t *loffs)
{
int res;
printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
//1.校验传输数据大小,如果用户空间传输数据的大小大于内核空间,需要更正传输数据大小
if(size>sizeof(kbuf)) size=sizeof(kbuf);
res=copy_from_user(kbuf,ubuf,size);
if(res)
{
printk("copy from user is error\n");
return -EIO;
}
printk("copy from user kbuf=%s\n",kbuf);
//2.实现灯点亮和熄灭的过程
if(kbuf[0]=='1')
{
if(kbuf[1]=='1')
{
GPIOE->ODR|=(0x1<<10);
}
else if(kbuf[1]=='0')
{
GPIOE->ODR&=(~(0x1<<10));
}
}
if(kbuf[0]=='2')
{
if(kbuf[1]=='1')
{
GPIOF->ODR|=(0x1<<10);
}
else if(kbuf[1]=='0')
{
GPIOF->ODR&=(~(0x1<<10));
}
}
if(kbuf[0]=='3')
{
if(kbuf[1]=='1')
{
GPIOE->ODR|=(0x1<<8);
}
else if(kbuf[1]=='0')
{
GPIOE->ODR&=(~(0x1<<8));
}
}
return size;
}
int mycdev_close(struct inode *inode,struct file *file)
{
printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
return 0;
}
const 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,CNAME,&fops);
if(major<0)
{
printk("register chrdev is error\n");
return major;
}
printk("major=%d\n",major);
//将物理地址映射为虚拟地址
RCC=ioremap(PHY_RCC,4);
if(NULL==RCC)
{
printk("rcc ioremap is error\n");
return -ENOMEM;
}
GPIOE=ioremap(PHY_GPIOE,sizeof(gpio_t));
if(NULL==GPIOE)
{
printk("gpioe ioremap is error\n");
return -ENOMEM;
}
GPIOF=ioremap(PHY_GPIOF,sizeof(gpio_t));
if(NULL==GPIOF)
{
printk("gpiof ioremap is error\n");
return -ENOMEM;
}
//引脚初始化
*RCC|=(0x1<<4);
*RCC|=(0x1<<5);
GPIOE->MODER&=(~(0x3<<20));
GPIOE->MODER|=(0x1<<20);
GPIOF->MODER&=(~(0x3<<20));
GPIOF->MODER|=(0x1<<20);
GPIOE->MODER&=(~(0x3<<16));
GPIOE->MODER|=(0x1<<16);
return 0;
}
static void __exit mycdev_exit(void)
{
//2.注销字符设备驱动,销毁映射
iounmap(GPIOE);
iounmap(GPIOF);
iounmap(RCC);
unregister_chrdev(major,CNAME);
}
module_init(mycdev_init);
module_exit(mycdev_exit);
MODULE_LICENSE("GPL");
测试文件:
#include
#include
#include
#include
#include
#include
#include
char buf[128]={""};
int main(int argc, char const *argv[])
{
int fd=-1;
fd=open("/dev/myled",O_RDWR);
if(-1==fd)
{
perror("open is error\n");
exit(1);
}
while(1)
{
buf[0]='1';
buf[1]='1';
write(fd,buf,sizeof(buf));
sleep(1);
buf[0]='1';
buf[1]='0';
write(fd,buf,sizeof(buf));
sleep(1);
buf[0]='2';
buf[1]='1';
write(fd,buf,sizeof(buf));
sleep(1);
buf[0]='2';
buf[1]='0';
write(fd,buf,sizeof(buf));
sleep(1);
buf[0]='3';
buf[1]='1';
write(fd,buf,sizeof(buf));
sleep(1);
buf[0]='3';
buf[1]='0';
write(fd,buf,sizeof(buf));
sleep(1);
}
close(fd);
return 0;
}
测深结果:
stm32流水灯