驱动开发day3

头文件:

#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流水灯

你可能感兴趣的:(驱动开发,arm,嵌入式硬件)