head.h
#ifndef __HEAD_H__
#define __HEAD_H__
typedef struct{
unsigned int MODER;
unsigned int OTYPER;
unsigned int OSPEEDR;
unsigned int PUPDR;
unsigned int IDR;
unsigned int ODR;
}gpio_t;
#define PHY_GPIOE 0X50006000
#define PHY_GPIOF 0X50007000
#define PHY_RCC 0X50000A28
#endif
demo.c
#include
#include
#include
#include
#include"head.h"
int major;
char kbuf[128]={0}; //存放传入内核的数据
gpio_t *vir_led1;
gpio_t *vir_led2;
gpio_t *vir_led3;
unsigned int *vir_rcc;
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)
{
int ret;
//向用户空间读取拷贝
if(size > sizeof(kbuf)) //内核最大输入限制
size = sizeof(kbuf);
ret = copy_to_user(ubuf, kbuf, size);
if (ret) //拷贝失败
{
printk("copy_to_user filed\n");
return ret;
}
printk("%s:%s:%d\n", __FILE__,__func__, __LINE__);
return 0;
}
ssize_t mycdev_write(struct file *file, const char *ubuf, size_t size, loff_t *lof)
{
int ret;
//从用户空间读取数据
if(size > sizeof(kbuf)) //内核最大输入限制
size = sizeof(kbuf);
ret = copy_from_user(kbuf, ubuf, size);
if (ret) //拷贝失败
{
printk("copy_to_user filed\n");
return ret;
}
switch(kbuf[0])
{
case '1': //LED1
if (kbuf[1] == '0') //关灯
vir_led1->ODR &= (~(1<<10));
else //开灯
vir_led1->ODR |= 1<<10;
break;
case '2': //LED2
if (kbuf[1] == '0') //关灯
vir_led2->ODR &= (~(1<<10));
else//开灯
vir_led2->ODR |= 1<<10;
break;
case '3': //LED3
if (kbuf[1] == '0') //关灯
vir_led3->ODR &= (~(1<<8));
else //开灯
vir_led3->ODR |= 1<<8;
break;
}
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, "mychrdev", &fops);
if (major < 0)
{
printk("字符设备驱动注册失败\n");
return major;
}
printk("字符设备驱动注册成功:major=%d\n", major);
//寄存器地址的映射
vir_led1 = ioremap(PHY_GPIOE, sizeof(gpio_t));
if (NULL == vir_led1)
{
printk("ioremap filed:%d\n", __LINE__);
return -ENOMEM;
}
vir_led2 = ioremap(PHY_GPIOF, sizeof(gpio_t));
if (NULL == vir_led2)
{
printk("ioremap filed:%d\n", __LINE__);
return -ENOMEM;
}
vir_led3 = ioremap(PHY_GPIOE, sizeof(gpio_t));
if (NULL == vir_led1)
{
printk("ioremap filed:%d\n", __LINE__);
return -ENOMEM;
}
vir_rcc = ioremap(PHY_RCC, 4);
if (NULL == vir_rcc)
{
printk("ioremap filed:%d\n", __LINE__);
return -ENOMEM;
}
printk("物理地址映射成功\n");
//寄存器的初始化
//rcc
(*vir_rcc) |= (3<<4);
//led1
vir_led1->MODER &= (~(3<<20));
vir_led1->MODER |= (1<<20);
vir_led1->ODR &= (~(1<<10));
//led2
vir_led2->MODER &= (~(3<<20));
vir_led2->MODER |= (1<<20);
vir_led2->ODR &= (~(1<<10));
//led3
vir_led3->MODER &= (~(3<<16));
vir_led1->MODER |= (1<<16);
vir_led1->ODR &= (~(1<<8));
printk("寄存器初始化成功\n");
return 0;
}
static void __exit mycdev_exit(void)
{
//取消地址映射
iounmap(vir_led1);
iounmap(vir_led2);
iounmap(vir_rcc);
//注销字符设备驱动
unregister_chrdev(major,"mychrdev");
}
module_init(mycdev_init);
module_exit(mycdev_exit);
MODULE_LICENSE("GPL");
text.c
#include
#include
#include
#include
#include
#include
#include
int main(int argc, char const *argv[])
{
char buf[128] = {0};
int fd = open("/dev/mychrdev", O_RDWR);
if (fd < 0)
{
printf("打开设备文件失败\n");
exit(-1);
}
while (1)
{
//从终端读取
printf("请输入两个字符\n");
printf("第一个字符:1(LED1) 2(LED2) 3(LED3)\n");
printf("第二个字符:0(关灯) 1(开灯)\n");
printf("请输入>>>");
fgets(buf,sizeof(buf), stdin);
buf[strlen(buf)-1] = '\0';
//向设备文件中写
write(fd, buf, sizeof(buf));
}
close(fd);
return 0;
}