驱动风扇和蜂鸣器工作
头文件
#ifndef __HEAD_H__
#define __HEAD_H__
typedef struct{
unsigned int MODER;
unsigned int OTYPE;
unsigned int SPEEDER;
unsigned int PUDR;
unsigned int IDR;
unsigned int ODR;
}gpio_t;
#define GPIO_B 0x50003000
#define GPIO_E 0x50006000
#define GPIO_F 0x50007000
#define RCC 0x50000A28
// #define GPIOE_MODER 0x50006000
// #define GPIOE_ODR 0x50006014
// #define GPIOE_RCC 0x50000A28
#endif
应用层代码
#include<stdio.h>
#include<stdlib.h>
#include<sys/stat.h>
#include<sys/types.h>
#include<unistd.h>
#include<fcntl.h>
#include<string.h>
int main(int argc, char const *argv[])
{
char buf[128]="";
int fd=open("/dev/chardev",O_RDWR);
if (fd < 0)
{
printf("Error opening /dev/chardev\n");
return -1;
}
while(1)
{
// printf("please input first characters:led1:1,led2:2,led3:3\n");
// printf("please input second characters:led off:0,led on:1\n");
printf("please input first characters:beep 1,fan 2\n");
printf("please input second characters:beep or fan off:0,beep or fan on:1\n");
printf("please input two characters:");
fgets(buf,sizeof(buf),stdin);
buf[strlen(buf)-1] = '\0';
write(fd,buf,sizeof(buf));
memset(buf,0,sizeof(buf));
read(fd,buf,sizeof(buf));
}
printf("%s\n",buf);
close(fd);
return 0;
}
驱动代码
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/io.h>
#include <linux/device.h>
#include "head.h"
char kbuf[128]="";
gpio_t *ptr_gpiob;
gpio_t *ptr_gpioe;
gpio_t *ptr_gpiof;
unsigned int *ptr_rcc;
struct class *clas;
struct device *dev;
int chardev_open(struct inode *inode, struct file *file)
{
printk("%s:%s:%d",__FILE__,__func__,__LINE__);
return 0;
}
ssize_t chardev_read(struct file *file, char __user *user, size_t size, loff_t *lof)
{
if(sizeof(kbuf)<size)
{
size=sizeof(kbuf);
}
copy_to_user(user, kbuf, size);
// printk("%s:%s:%d",__FILE__,__func__,__LINE__);
return 0;
}
ssize_t chardev_write(struct file *file, const char __user *user, size_t size, loff_t *lof)
{
if(sizeof(kbuf)<size)
{
size=sizeof(kbuf);
}
copy_from_user(kbuf, user, size);
switch(kbuf[0])
{
case '1':
{
if(kbuf[1]=='1')
{
ptr_gpiob->ODR|=(1<<6);
}
else if(kbuf[1]=='0')
{
ptr_gpiob->ODR&=(~(1<<6));
}
}break;
case '2':
{
if(kbuf[1]=='1')
{
ptr_gpioe->ODR|=(1<<9);
}
else if(kbuf[1]=='0')
{
ptr_gpioe->ODR&=(~(1<<9));
}
}
}
// switch(kbuf[0])
// {
// case '1':
// {
// if(kbuf[1]=='1')
// {
// (*ptr_gpioe).ODR|=(1<<10);
// }
// else if(kbuf[1]=='0')
// {
// (*ptr_gpioe).ODR&=(~(1<<10));
// }
// }break;
// case '2':
// {
// if(kbuf[1]=='1')
// {
// (*ptr_gpiof).ODR|=(1<<10);
// }
// else if(kbuf[1]=='0')
// {
// (*ptr_gpiof).ODR&=(~(1<<10));
// }
// }break;
// case '3':
// {
// if(kbuf[1]=='1')
// {
// (*ptr_gpioe).ODR|=(1<<8);
// }
// else if(kbuf[1]=='0')
// {
// (*ptr_gpioe).ODR&=(~(1<<8));
// }
// }
// }
// printk("%s:%s:%d",__FILE__,__func__,__LINE__);
return 0;
}
int chardev_release(struct inode *inode, struct file *file)
{
printk("%s:%s:%d",__FILE__,__func__,__LINE__);
return 0;
}
int major;
struct file_operations fop={
.open=chardev_open,
.read=chardev_read,
.write=chardev_write,
.release=chardev_release,
};
static int __init demo_init(void)
{
major=register_chrdev(0, "chardev",&fop);
if(major<0)
{
printk("char device register failed\n");
return major;
}
printk("char device register successed:%d\n",major);
//配置自动生成设备文件
clas=class_create(THIS_MODULE,"chardev");
if (IS_ERR(clas))
{
printk("向上提交目录失败\n");
return PTR_ERR(clas);
}
dev=device_create(clas,NULL,MKDEV(major,0),NULL,"chardev");
if (IS_ERR(dev))
{
printk("向上提交目录失败\n");
return PTR_ERR(dev);
}
printk("device file created successfully\n");
//蜂鸣器物理映射和寄存器配置
ptr_gpiob=ioremap(GPIO_B,sizeof(gpio_t));
if(ptr_gpiob==NULL)
{
printk("ptr_gpiob failed\n");
return -ENOMEM;
}
ptr_rcc=ioremap(RCC,4);
if(ptr_rcc==NULL)
{
printk("ptr_rcc failed\n");
return -ENOMEM;
}
*ptr_rcc|=(1<<1);
(*ptr_gpiob).MODER&=(~(0x3<<12));
(*ptr_gpiob).MODER|=(1<<12);
(*ptr_gpiob).ODR&=(~(1<<6));
//风扇物理映射和寄存器配置
ptr_gpioe=ioremap(GPIO_E,sizeof(gpio_t));
if(ptr_gpioe==NULL)
{
printk("ptr_gpiof failed\n");
return -ENOMEM;
}
*ptr_rcc|=(1<<4);
(*ptr_gpioe).MODER&=(~(0x3<<18));
(*ptr_gpioe).MODER|=(1<<18);
(*ptr_gpioe).ODR&=(~(1<<9));
//led灯的物理映射和寄存器配置
// ptr_gpioe=ioremap(GPIO_E,sizeof(gpio_t));
// if(ptr_gpioe==NULL)
// {
// printk("ptr_moder failed\n");
// return -ENOMEM;
// }
// ptr_gpiof=ioremap(GPIO_F,sizeof(gpio_t));
// if(ptr_gpiof==NULL)
// {
// printk("ptr_odr failed\n");
// return -ENOMEM;
// }
// ptr_rcc=ioremap(RCC,4);
// if(ptr_rcc==NULL)
// {
// printk("ptr_rcc failed\n");
// return -ENOMEM;
// }
// (*ptr_rcc) |= (1 <<4);
// (*ptr_gpioe).MODER &= (~(3 <<20));
// (*ptr_gpioe).MODER|= (1 <<20);
// (*ptr_gpioe).ODR |= (1 <<10);
// (*ptr_rcc) |= (1 <<5);
// (*ptr_gpiof).MODER &= (~(3 <<20));
// (*ptr_gpiof).MODER|= (1 <<20);
// (*ptr_gpiof).ODR |= (1 <<10);
// (*ptr_rcc) |= (1 <<4);
// (*ptr_gpioe).MODER &= (~(3 <<16));
// (*ptr_gpioe).MODER|= (1 <<16);
// (*ptr_gpioe).ODR |= (1 <<8);
return 0;
}
static void __exit demo_exit(void)
{
device_destroy(clas,MKDEV(major,0));
class_destroy(clas);
iounmap(ptr_gpiob);
iounmap(ptr_gpioe);
iounmap(ptr_gpiof);
iounmap(ptr_rcc);
unregister_chrdev(major, "chardev");
}
module_init(demo_init);
module_exit(demo_exit);
MODULE_LICENSE("GPL");