This commit is contained in:
unknown 2022-01-09 16:22:40 +08:00
parent 4082b4f8d1
commit 107602167c
29 changed files with 0 additions and 1786 deletions

View File

@ -1,22 +0,0 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
int main(int argc, char **argv)
{
unsigned int keyval;
int fd = 0;
/* 打开驱动文件 */
fd = open(argv[1], O_RDWR);
if (fd<0) printf("can't open %s file\n",argv[1]);
while(1)
{
read(fd, &keyval,sizeof(keyval));
printf("key_value = %d\n",keyval);
}
return 0;
}

View File

@ -1,38 +0,0 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
int main(int argc, char **argv)
{
int fd;
char* filename=NULL;
int val;
filename = argv[1];
fd = open(filename, O_RDWR);//打开dev/设备文件
if (fd < 0)//小于0说明没有成功
{
printf("error, can't open %s\n", filename);
return 0;
}
if(argc !=3)
{
printf(argv[1]);//打印用法
}
if(!strcmp(argv[2], "on")) //如果输入等于on则LED亮
val = 0;
else if(!strcmp(argv[2], "off")) //如果输入等于off则LED灭
val = 1;
else
goto error;
write(fd, &val, 4);//操作LED
close(fd);
return 0;
error:
printf("usage: ./led_dev.exe [device] [on/off]\n");
close(fd);
return -1;
}

View File

@ -1,37 +0,0 @@
#include <string.h>
#include <fcntl.h>
#include <linux/input.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#define CHECK_POINT
int main(int argc, char** argv)
{
int fd = open(argv[1],O_RDONLY);
#ifdef CHECK_POINT
printf("fd = %d\n",fd);
#endif
struct input_event t;
printf("size of t = %d\n",sizeof(t));
while(1)
{
printf("while -\n");
int len = read(fd, &t, sizeof(t));
if(len == sizeof(t))
{
printf("read over\n");
if(t.type==EV_KEY)
{
printf("key %d %s\n", t.code, (t.value) ? "Pressed" : "Released");
if(t.code == KEY_ESC)
break;
}
}
#ifdef CHECK_POINT
printf("len = %d\n",len);
#endif
}
return 0;
}

View File

@ -1,11 +0,0 @@
KERN_DIR = /home/lsw/licheepi/linux-5.7.1
all:
make -C $(KERN_DIR) M=$(shell pwd) modules
clean:
make -C $(KERN_DIR) M=$(shell pwd) modules clean
rm -rf modules.order *.ko
obj-m += at24c02.o

View File

@ -1,106 +0,0 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <asm/io.h> //含有ioremap函数iounmap函数
#include <asm/uaccess.h> //含有copy_from_user函数和含有copy_to_user函数
#include <linux/device.h> //含有类相关的设备函数
#include <linux/cdev.h>
#include <linux/platform_device.h> //包含platform函数
#include <linux/of.h> //包含设备树相关函数
#include <linux/i2c.h>
#include <linux/kobject.h> //包含sysfs文件系统对象类
#include <linux/sysfs.h> //包含sysfs操作文件函数
static char recv[16] = {0}; //保存接收数据
static struct kobject *at24c02_kobj; //定义一个led_kobj
struct i2c_client *at24c02_dev; //定义一个i2c设备结构体指针
static ssize_t at24c02_show(struct kobject* kobjs,struct kobj_attribute *attr,char *buf)
{
int ret;
ret = i2c_smbus_write_byte(at24c02_dev,0x02); //先发写地址操作
if(ret)
{
printk(KERN_ERR"write addr failed!\n");
return ret;
}
recv[0] = i2c_smbus_read_byte(at24c02_dev); //然后发读数据操作
return sprintf(buf,"read status register=0x%x\n",recv[0]);
}
static ssize_t at24c02_store(struct kobject *kobj, struct kobj_attribute *attr,const char *buf, size_t count)
{
int ret;
char data = 0x2f;
ret = i2c_smbus_write_i2c_block_data(at24c02_dev,0x02,1,&data);//写一个字节数据
if(!ret)
{
printk(KERN_ERR"write data failed!\n");
}
return count;
}
static struct kobj_attribute at24c02_attr = __ATTR(at24c02_dev,0660,at24c02_show,at24c02_store);
static int at24c02_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
int ret;
at24c02_kobj = kobject_create_and_add("sys_at24c02",NULL);
if(at24c02_kobj == NULL)
{
printk(KERN_INFO"create at24c02_kobj failed!\n");
return -1;
}
ret = sysfs_create_file(at24c02_kobj, &at24c02_attr.attr);
if(ret != 0)
{
printk(KERN_INFO"create at24c02_dev file failed!\n");
return -1;
}
at24c02_dev = client; //初始化i2c设备结构体指针
return 0;
}
static int at24c02_remove(struct i2c_client *client)
{
sysfs_remove_file(at24c02_kobj, &at24c02_attr.attr); //删除属性
kobject_put(at24c02_kobj); //删除对象
printk(KERN_INFO "exit sysfs at24c02!\n");
return 0;
}
static const struct i2c_device_id at24c02_id[] = {
{ "test,at24c0x", 0 },
{ }
};
static const struct of_device_id at24c02_of_match[] = {
{ .compatible = "test,at24c0x"},
{ },
};
MODULE_DEVICE_TABLE(of, at24c02_of_match);
static struct i2c_driver at24c02_driver = {
.driver = {
.name = "test,at24c0x",
.owner = THIS_MODULE,
.of_match_table = at24c02_of_match,
},
.probe = at24c02_probe,
.remove = at24c02_remove,
.id_table = at24c02_id,
};
module_i2c_driver(at24c02_driver);
MODULE_LICENSE("GPL"); //不加的话加载会有错误提醒
MODULE_AUTHOR("1477153217@qq.com"); //作者
MODULE_VERSION("0.1"); //版本
MODULE_DESCRIPTION("at24c02_driver"); //简单的描述

View File

@ -1,11 +0,0 @@
KERN_DIR = /home/lsw/licheepi/linux-5.7.1
all:
make -C $(KERN_DIR) M=$(shell pwd) modules
clean:
make -C $(KERN_DIR) M=$(shell pwd) modules clean
rm -rf modules.order *.ko
obj-m += myfb.o

View File

@ -1,128 +0,0 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <asm/io.h> //含有ioremap函数iounmap函数
#include <asm/uaccess.h> //含有copy_from_user函数和含有copy_to_user函数
#include <linux/device.h> //含有类相关的设备函数
#include <linux/cdev.h>
#include <linux/platform_device.h> //包含platform函数
#include <linux/of.h> //包含设备树相关函数
#include <linux/fb.h> //包含frame buffer
#include <linux/spi/spi.h>
struct fb_info *myfb; //定义一个fb_info
struct spi_device *myfb_spi; //spi接口
static struct of_device_id myfb_spi_match_table[] = {
{.compatible = "test,myfb-spi"},
{},
};
MODULE_DEVICE_TABLE(of, myfb_spi_match_table);
static int myfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
{
if (var->xres < 0 || var->yres < 0 ||
var->xres > 240 || var->yres > 240 ||
var->bits_per_pixel != 16)
return -EINVAL;
var->xres_virtual = var->xres;
var->yres_virtual = var->yres;
return 0;
}
static inline u32 chan_to_field(u32 chan, struct fb_bitfield *bf)
{
return ((chan & 0xffff) >> (16 - bf->length)) << bf->offset;
}
static int myfb_setcolreg(unsigned regno, unsigned red, unsigned green,unsigned blue, unsigned transp, struct fb_info *info)
{
u32 *pal = info->pseudo_palette;
if (regno > 15)
return -EINVAL;
pal[regno] = chan_to_field(red, &info->var.red)
| chan_to_field(green, &info->var.green)
| chan_to_field(blue, &info->var.blue)
| chan_to_field(transp, &info->var.transp);
return 0;
}
static int myfb_blank(int blank, struct fb_info *info)
{
return 1; /* get fb_blank to set the colormap to all black */
}
struct fb_ops myfb_ops = //定义一个fb_ops结构体指针
{
.owner = THIS_MODULE,
.fb_check_var = myfb_check_var,
//.fb_set_par = myfb_set_par;
.fb_setcolreg = myfb_setcolreg,
.fb_fillrect = cfb_fillrect,
.fb_copyarea = cfb_copyarea,
.fb_imageblit = cfb_imageblit,
.fb_blank = myfb_blank,
};
static int myfb_spi_probe(struct spi_device *spi)
{
int ret;
printk(KERN_ERR"register myfb_spi_probe!\n");
myfb_spi = spi_dev_get(spi);
printk(KERN_ERR"register myfb_probe dev!\n");
myfb = framebuffer_alloc(sizeof(struct fb_info), &spi->dev); //向内核申请fb_info结构体
//初始化底层操作结构体
myfb->fbops = &myfb_ops;
ret = register_framebuffer(myfb);
if(ret)
{
framebuffer_release(myfb);
unregister_framebuffer(myfb);
printk(KERN_ERR"fail to register fb dev!\n");
return -1;
}
return 0;
}
static int myfb_spi_remove(struct spi_device *spi)
{
framebuffer_release(myfb);
unregister_framebuffer(myfb);
printk(KERN_INFO "exit myfb!\n");
return 0;
}
static struct spi_driver myfb_spi_driver = {
.driver = {
.name = "myfb",
.owner = THIS_MODULE,
.of_match_table = myfb_spi_match_table,
},
.probe = myfb_spi_probe,
.remove = myfb_spi_remove,
};
module_spi_driver(myfb_spi_driver);
MODULE_LICENSE("GPL"); //不加的话加载会有错误提醒
MODULE_AUTHOR("1477153217@qq.com"); //作者
MODULE_VERSION("0.1"); //版本
MODULE_DESCRIPTION("myfb_spi_driver"); //简单的描述

View File

@ -1,11 +0,0 @@
KERN_DIR = /home/lsw/licheepi/linux-5.7.1
all:
make -C $(KERN_DIR) M=$(shell pwd) modules
clean:
make -C $(KERN_DIR) M=$(shell pwd) modules clean
rm -rf modules.order *.ko
obj-m +=gpio_subsys.o

View File

@ -1,109 +0,0 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <asm/io.h> //含有ioremap函数iounmap函数
#include <asm/uaccess.h> //含有copy_from_user函数和含有copy_to_user函数
#include <linux/device.h> //含有类相关的设备函数
#include <linux/cdev.h>
#include <linux/platform_device.h> //包含platform函数
#include <linux/of.h> //包含设备树相关函数
#include <linux/spi/spi.h>
#include <linux/kobject.h> //包含sysfs文件系统对象类
#include <linux/sysfs.h> //包含sysfs操作文件函数
#include <linux/gpio/consumer.h> //包含gpio子系统接口
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/gpio.h> //包含gpio一些宏
static struct kobject *led_kobj; //定义一个led_kobj
struct gpio_desc *led_pin; //gpio资源
static ssize_t led_show(struct kobject* kobjs,struct kobj_attribute *attr,char *buf)
{
return sprintf(buf,"led status=%d\n",gpiod_get_value(led_pin));
}
static ssize_t led_store(struct kobject *kobj, struct kobj_attribute *attr,const char *buf, size_t count)
{
if(0 == memcmp(buf,"on",2))
{
gpiod_set_value(led_pin,0);
}
else if(0 == memcmp(buf,"off",3))
{
gpiod_set_value(led_pin,1);
}
else
{
printk(KERN_INFO "Not support cmd\n");
}
return count;
}
static struct kobj_attribute led_attr = __ATTR(led_dev,0660,led_show,led_store);
static int led_probe(struct platform_device *pdev)
{
int ret;
led_kobj = kobject_create_and_add("sys_led",NULL);
if(led_kobj == NULL)
{
printk(KERN_INFO"create led_kobj failed!\n");
return -1;
}
ret = sysfs_create_file(led_kobj,&led_attr.attr);
if(ret != 0)
{
printk(KERN_INFO"create w25q128_dev file failed!\n");
return -1;
}
led_pin = devm_gpiod_get(&pdev->dev,"led",GPIOF_OUT_INIT_LOW);
if(IS_ERR(led_pin))
{
printk(KERN_ERR"Get gpio resource failed!\n");
return -1;
}
gpiod_direction_output(led_pin,0);
return 0;
}
static int led_remove(struct platform_device *pdev)
{
sysfs_remove_file(led_kobj, &led_attr.attr); //删除属性
kobject_put(led_kobj); //删除对象
devm_gpiod_put(&pdev->dev,led_pin);
printk(KERN_INFO "exit sysfs sys_led!\n");
return 0;
}
static struct of_device_id led_match_table[] = {
{.compatible = "test,led_subsys",},
};
static struct platform_device_id led_ids[] = {
{.name = "led_subsys",},
};
static struct platform_driver led_cdev = {
.driver = {
.name = "led_subsys",
.owner = THIS_MODULE,
.of_match_table = led_match_table,
},
.probe = led_probe,
.remove = led_remove,
.id_table = led_ids,
};
module_platform_driver(led_cdev);
MODULE_LICENSE("GPL"); //不加的话加载会有错误提醒
MODULE_AUTHOR("1477153217@qq.com"); //作者
MODULE_VERSION("0.1"); //版本
MODULE_DESCRIPTION("led_cdev"); //简单的描述

View File

@ -1,11 +0,0 @@
KERN_DIR = /home/lsw/licheepi/linux-5.7.1
all:
make -C $(KERN_DIR) M=$(shell pwd) modules
clean:
make -C $(KERN_DIR) M=$(shell pwd) modules clean
rm -rf modules.order *.ko
obj-m +=key_dev_platform.o

View File

@ -1,150 +0,0 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <asm/io.h> //含有iomap函数iounmap函数
#include <asm/uaccess.h> //含有copy_from_user函数
#include <linux/device.h> //含有类相关的处理函数
#include <linux/irq.h> //含有IRQ_HANDLED和IRQ_TYPE_EDGE_RISING
#include <linux/interrupt.h> //含有request_irq、free_irq函数
#include <linux/cdev.h>
static dev_t btn_cdev_num; //定义一个设备号
static struct cdev *btn_cdev; //定义一个设备管理结构体指针
static struct class *btn_class; //定义一个设备类
static struct device *btn; //定义一个设备
#define KEYADC_BASE (0x01C22800)
#define KEYADC_CTRL_REG (KEYADC_BASE+0x00)
#define KEYADC_INTC_REG (KEYADC_BASE+0x04)
#define KEYADC_INTS_REG (KEYADC_BASE+0x08)
#define KEYADC_DATA_REG (KEYADC_BASE+0x0C)
ssize_t volatile *keyadc_ctrl;
ssize_t volatile *keyadc_intc;
ssize_t volatile *keyadc_ints;
ssize_t volatile *keyadc_data;
static unsigned int ev_press; //一个全局变量,记录中断事件状态
DECLARE_WAIT_QUEUE_HEAD(btn_waitq);//注册一个等待队列button_waitq用宏来申明一个全局变量
static unsigned int key_value = 0; //定义一个变量保存按键值
static irqreturn_t btn_irq(int irq, void *dev_id)
{
wake_up_interruptible(&btn_waitq); /* 唤醒休眠的进程即调用read函数的进程 */
ev_press = 1;
*keyadc_ints |= ((1<<0)|(1<<1) | (1<<2) |(1<<3)|(1<<4));
return IRQ_HANDLED;
}
static int btn_cdev_open (struct inode * inode, struct file * file)
{
*keyadc_intc |= ((1<<0)|(1<<1)|(1<<4));
*keyadc_ctrl |= (1<<7);
*keyadc_ctrl &= ~(0xf<<8);
*keyadc_ctrl |= (1<<0);
return 0;
}
static int btn_cdev_close(struct inode * inode, struct file * file)
{
return 0;
}
static ssize_t btn_cdev_read(struct file * file, char __user * userbuf, size_t count, loff_t * off)
{
int ret;
unsigned int adc_value;
adc_value = *(keyadc_data);
//将当前进程放入等待队列button_waitq中,并且释放CPU进入睡眠状态
wait_event_interruptible(btn_waitq, ev_press!=0);
ret = copy_to_user(userbuf, &adc_value, 4);//将取得的按键值传给上层应用
printk(KERN_WARNING"key adc = %d\n",(adc_value&(0x3f)));
printk(KERN_WARNING"key statue = 0x%x\n",*(keyadc_ints));
ev_press = 0;//按键已经处理可以继续睡眠
if(ret)
{
printk("copy error\n");
return -1;
}
return 1;
}
static struct file_operations btn_cdev_ops = {
.owner = THIS_MODULE,
.open = btn_cdev_open,
.read = btn_cdev_read,
.release = btn_cdev_close,
};
static int btn_cdev_init(void)
{
int ret;
btn_cdev = cdev_alloc(); //动态申请一个设备结构体
if(btn_cdev == NULL)
{
printk(KERN_WARNING"cdev_alloc failed!\n");
return -1;
}
ret = alloc_chrdev_region(&btn_cdev_num,0,1,"button"); //动态申请一个设备号
if(ret !=0)
{
printk(KERN_WARNING"alloc_chrdev_region failed!\n");
return -1;
}
btn_cdev->owner = THIS_MODULE; //初始化设备管理结构体的owner为THIS_MODULE
btn_cdev->ops = &btn_cdev_ops; //初始化设备操作函数指针为led_ops函数
cdev_add(btn_cdev,btn_cdev_num,1); //将设备添加到内核中
btn_class = class_create(THIS_MODULE, "button"); //创建一个名为led_class的类
if(btn_class == NULL)
{
printk(KERN_WARNING"btn_class failed!\n");
return -1;
}
btn = device_create(btn_class,NULL,btn_cdev_num,NULL,"button0"); //创建一个设备名为led0
if(IS_ERR(btn))
{
printk(KERN_WARNING"device_create failed!\n");
return -1;
}
keyadc_ctrl = ioremap(KEYADC_CTRL_REG, 4);//重映射
keyadc_intc = ioremap(KEYADC_INTC_REG, 4);//重映射
keyadc_ints = ioremap(KEYADC_INTS_REG, 4);//重映射
keyadc_data = ioremap(KEYADC_DATA_REG, 4);//重映射
ret = request_any_context_irq(35, btn_irq, 0 , "btn",(void*)&key_value);
if(ret) //返回不为0表示申请失败
{
printk("request irq failed!\n");
return -1;
}
return 0;
}
static void btn_cdev_exit(void)
{
cdev_del(btn_cdev); //从内核中删除设备管理结构体
unregister_chrdev_region(btn_cdev_num,1); //注销设备号
device_destroy(btn_class,btn_cdev_num); //删除设备节点
class_destroy(btn_class); //删除设备类
iounmap(keyadc_ctrl);//取消重映射
iounmap(keyadc_intc);//取消重映射
iounmap(keyadc_ints);//取消重映射
iounmap(keyadc_data);//取消重映射
free_irq(35,(void*)&key_value);//释放中断
printk("unregister btn_cdev\n");
}
module_init(btn_cdev_init);
module_exit(btn_cdev_exit);
MODULE_LICENSE("GPL");

View File

@ -1,174 +0,0 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <asm/io.h> //含有ioremap函数iounmap函数
#include <asm/uaccess.h> //含有copy_from_user函数和含有copy_to_user函数
#include <linux/device.h> //含有类相关的设备函数
#include <linux/cdev.h>
#include <linux/platform_device.h> //包含platform函数
#include <linux/of.h> //包含设备树相关函数
#include <linux/irq.h> //含有IRQ_HANDLED和IRQ_TYPE_EDGE_RISING
#include <linux/interrupt.h> //含有request_irq、free_irq函数
static dev_t btn_cdev_num; //定义一个设备号
static struct cdev *btn_cdev; //定义一个设备管理结构体指针
static struct class *btn_class; //定义一个设备类
static struct device *btn; //定义一个设备
ssize_t volatile *keyadc_ctrl;
ssize_t volatile *keyadc_intc;
ssize_t volatile *keyadc_ints;
ssize_t volatile *keyadc_data;
static unsigned int ev_press; //一个全局变量,记录中断事件状态
DECLARE_WAIT_QUEUE_HEAD(btn_waitq);//注册一个等待队列button_waitq用宏来申明一个全局变量
static unsigned int key_value = 0; //定义一个变量保存按键值
static irqreturn_t btn_irq(int irq, void *dev_id)
{
ssize_t ints_clr = *keyadc_ints;
ints_clr = *keyadc_ints;
wake_up_interruptible(&btn_waitq); /* 唤醒休眠的进程即调用read函数的进程 */
ev_press = 1;
*keyadc_ints |= ints_clr;
return IRQ_HANDLED;
}
static int btn_cdev_open (struct inode * inode, struct file * file)
{
*keyadc_ctrl&=0;
*keyadc_ctrl |= (2<<24) | (1<<8) | (1<<6);
*keyadc_intc |= (1<<4) | (1<<1);
*keyadc_ctrl |= (1<<0);
return 0;
}
static int btn_cdev_close(struct inode * inode, struct file * file)
{
return 0;
}
static ssize_t btn_cdev_read(struct file * file, char __user * userbuf, size_t count, loff_t * off)
{
int ret;
unsigned int adc_value;
adc_value = *(keyadc_data);
//将当前进程放入等待队列button_waitq中,并且释放CPU进入睡眠状态
wait_event_interruptible(btn_waitq, ev_press!=0);
ret = copy_to_user(userbuf, &adc_value, 4);//将取得的按键值传给上层应用
printk(KERN_WARNING"key adc = %d\n",(adc_value&(0x3f)));
printk(KERN_WARNING"key statue = 0x%x\n",*(keyadc_ints));
ev_press = 0;//按键已经处理可以继续睡眠
if(ret)
{
printk("copy error\n");
return -1;
}
return 1;
}
static struct file_operations btn_cdev_ops = {
.owner = THIS_MODULE,
.open = btn_cdev_open,
.read = btn_cdev_read,
.release = btn_cdev_close,
};
static int btn_probe(struct platform_device *pdev)
{
int ret;
struct resource *res;
btn_cdev = cdev_alloc(); //动态申请一个设备结构体
if(btn_cdev == NULL)
{
printk(KERN_WARNING"cdev_alloc failed!\n");
return -1;
}
ret = alloc_chrdev_region(&btn_cdev_num,0,1,"button"); //动态申请一个设备号
if(ret !=0)
{
printk(KERN_WARNING"alloc_chrdev_region failed!\n");
return -1;
}
btn_cdev->owner = THIS_MODULE; //初始化设备管理结构体的owner为THIS_MODULE
btn_cdev->ops = &btn_cdev_ops; //初始化设备操作函数指针为led_ops函数
cdev_add(btn_cdev,btn_cdev_num,1); //将设备添加到内核中
btn_class = class_create(THIS_MODULE, "button"); //创建一个名为led_class的类
if(btn_class == NULL)
{
printk(KERN_WARNING"btn_class failed!\n");
return -1;
}
btn = device_create(btn_class,NULL,btn_cdev_num,NULL,"button0"); //创建一个设备名为led0
if(IS_ERR(btn))
{
printk(KERN_WARNING"device_create failed!\n");
return -1;
}
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); //获取device中的LRADC_CTRL
keyadc_ctrl = ioremap(res->start,(res->end - res->start)+1);
res = platform_get_resource(pdev, IORESOURCE_MEM, 1); //获取device中的LRADC_INTC
keyadc_intc = ioremap(res->start,(res->end - res->start)+1);
res = platform_get_resource(pdev, IORESOURCE_MEM, 2); //获取device中的LRADC_INTS
keyadc_ints = ioremap(res->start,(res->end - res->start)+1);
res = platform_get_resource(pdev, IORESOURCE_MEM, 3); //获取device中的LRADC_DATA
keyadc_data = ioremap(res->start,(res->end - res->start)+1);
ret = devm_request_irq(&pdev->dev, platform_get_irq(pdev, 0), btn_irq, 0, "mykey", (void*)&key_value);
if(ret)
{
return ret;
}
return 0;
}
static int btn_remove(struct platform_device *pdev)
{
iounmap(keyadc_ctrl); //取消LRADC_CTRL映射
iounmap(keyadc_intc); //取消LRADC_INTC映射
iounmap(keyadc_ints); //取消LRADC_INTS映射
iounmap(keyadc_data); //取消LRADC_DATA映射
cdev_del(btn_cdev); //从内核中删除设备管理结构体
unregister_chrdev_region(btn_cdev_num,1); //注销设备号
device_destroy(btn_class,btn_cdev_num); //删除设备节点
class_destroy(btn_class); //删除设备类
return 0;
}
static struct of_device_id btn_match_table[] = {
{.compatible = "mykey",},
};
static struct platform_device_id btn_device_ids[] = {
{.name = "btn",},
};
static struct platform_driver btn_driver=
{
.probe = btn_probe,
.remove = btn_remove,
.driver={
.name = "btn",
.of_match_table = btn_match_table,
},
.id_table = btn_device_ids,
};
module_platform_driver(btn_driver);
MODULE_LICENSE("GPL"); //不加的话加载会有错误提醒
MODULE_AUTHOR("1477153217@qq.com"); //作者
MODULE_VERSION("0.1"); //版本
MODULE_DESCRIPTION("btn_driver"); //简单的描述

View File

@ -1,11 +0,0 @@
KERN_DIR = /home/lsw/licheepi/linux-5.7.1
all:
make -C $(KERN_DIR) M=$(shell pwd) modules
clean:
make -C $(KERN_DIR) M=$(shell pwd) modules clean
rm -rf modules.order *.ko
obj-m +=mykeypad.o

View File

@ -1,163 +0,0 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <asm/io.h> //含有ioremap函数iounmap函数
#include <asm/uaccess.h> //含有copy_from_user函数和含有copy_to_user函数
#include <linux/device.h> //含有类相关的设备函数
#include <linux/cdev.h>
#include <linux/platform_device.h> //包含platform函数
#include <linux/of.h> //包含设备树相关函数
#include <linux/irq.h> //含有IRQ_HANDLED和IRQ_TYPE_EDGE_RISING
#include <linux/interrupt.h> //含有request_irq、free_irq函数
#include <linux/input.h>
#include <linux/irq.h>
struct input_dev *mykeypad_dev; //定义一个input_dev结构体
ssize_t volatile *keyadc_ctrl;
ssize_t volatile *keyadc_intc;
ssize_t volatile *keyadc_ints;
ssize_t volatile *keyadc_data;
static unsigned int key_value = 0; //定义一个变量保存按键值
static irqreturn_t mykeypad_irq (int irq, void *dev_id) //中断服务函数
{
ssize_t key_value;
/*上报事件*/
key_value = ((*keyadc_data)&(0x3f));
if(((*keyadc_ints)&(1<<1)) != 0)
{
if(key_value == 24)
{
input_event(mykeypad_dev, EV_KEY, KEY_A , 1); //上报EV_KEY类型,button按键,1(按下)
}
else if(key_value == 17)
{
input_event(mykeypad_dev, EV_KEY, KEY_B, 1); //上报EV_KEY类型,button按键,1(按下)
}
else if(key_value == 11)
{
input_event(mykeypad_dev, EV_KEY, KEY_C, 1); //上报EV_KEY类型,button按键,1(按下)
}
else
{
input_event(mykeypad_dev, EV_KEY, KEY_D, 1); //上报EV_KEY类型,button按键,1(按下)
}
}
else if(((*keyadc_ints)&(1<<4)) != 0)
{
if(key_value == 24)
{
input_event(mykeypad_dev, EV_KEY, KEY_A , 0); //上报EV_KEY类型,button按键,1(按下)
}
else if(key_value == 17)
{
input_event(mykeypad_dev, EV_KEY, KEY_B, 0); //上报EV_KEY类型,button按键,1(按下)
}
else if(key_value == 11)
{
input_event(mykeypad_dev, EV_KEY, KEY_C, 0); //上报EV_KEY类型,button按键,1(按下)
}
else
{
input_event(mykeypad_dev, EV_KEY, KEY_D, 0); //上报EV_KEY类型,button按键,1(按下)
}
}
input_sync(mykeypad_dev); // 上传同步事件,告诉系统有事件出现
*keyadc_ints |= ((1<<0) | (1<<1) | (1<<2) | (1<<3) | (1<<4));
return IRQ_HANDLED;
}
static int mykeypad_probe(struct platform_device *pdev)
{
int ret;
struct resource *res;
mykeypad_dev=input_allocate_device(); //向内核申请input_dev结构体
set_bit(EV_KEY,mykeypad_dev->evbit); //支持键盘事件
set_bit(EV_REP,mykeypad_dev->evbit); //支持键盘重复按事件
set_bit(KEY_A,mykeypad_dev->keybit); //支持按键 A
set_bit(KEY_B,mykeypad_dev->keybit); //支持按键 B
set_bit(KEY_C,mykeypad_dev->keybit); //支持按键 C
set_bit(KEY_D,mykeypad_dev->keybit); //支持按键 D
mykeypad_dev->name = pdev->name; //设备名称
mykeypad_dev->phys = "mykeypad/input0"; //设备文件路径
mykeypad_dev->open = NULL; //设备打开操作函数
mykeypad_dev->close = NULL; //设备关闭操作函数
mykeypad_dev->id.bustype = BUS_HOST; //设备总线类型
mykeypad_dev->id.vendor = 0x0001; //设备厂家编号
mykeypad_dev->id.product = 0x0001; //设备产品编号
mykeypad_dev->id.version = 0x0100; //设备版本
ret = input_register_device(mykeypad_dev); //注册input_dev
if(ret)
{
input_free_device(mykeypad_dev);
printk(KERN_ERR "regoster input device failed!\n");
return ret;
}
mykeypad_dev->name="mykeypad";
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); //获取device中的LRADC_CTRL
keyadc_ctrl = ioremap(res->start,(res->end - res->start)+1);
res = platform_get_resource(pdev, IORESOURCE_MEM, 1); //获取device中的LRADC_INTC
keyadc_intc = ioremap(res->start,(res->end - res->start)+1);
res = platform_get_resource(pdev, IORESOURCE_MEM, 2); //获取device中的LRADC_INTS
keyadc_ints = ioremap(res->start,(res->end - res->start)+1);
res = platform_get_resource(pdev, IORESOURCE_MEM, 3); //获取device中的LRADC_DATA
keyadc_data = ioremap(res->start,(res->end - res->start)+1);
ret = devm_request_irq(&pdev->dev, platform_get_irq(pdev, 0), mykeypad_irq, 0, "mykey", (void*)&key_value);
*keyadc_ctrl&=0;
*keyadc_ctrl |= (2<<24) | (1<<8) | (1<<6);
*keyadc_intc |= (1<<4) | (1<<1);
*keyadc_ctrl |= (1<<0);
if(ret)
{
return ret;
}
return 0;
}
static int mykeypad_remove(struct platform_device *pdev)
{
iounmap(keyadc_ctrl); //取消LRADC_CTRL映射
iounmap(keyadc_intc); //取消LRADC_INTC映射
iounmap(keyadc_ints); //取消LRADC_INTS映射
iounmap(keyadc_data); //取消LRADC_DATA映射
input_unregister_device(mykeypad_dev); //卸载类下的驱动设备
input_free_device(mykeypad_dev); //释放驱动结构体
return 0;
}
static struct of_device_id mykeypad_match_table[] = {
{.compatible = "mykeypad",},
};
static struct platform_device_id mykeypad_device_ids[] = {
{.name = "mykeypad",},
};
static struct platform_driver mykeypad_driver=
{
.probe = mykeypad_probe,
.remove = mykeypad_remove,
.driver={
.name = "mykeypad",
.of_match_table = mykeypad_match_table,
},
.id_table = mykeypad_device_ids,
};
module_platform_driver(mykeypad_driver);
MODULE_LICENSE("GPL"); //不加的话加载会有错误提醒
MODULE_AUTHOR("1477153217@qq.com"); //作者
MODULE_VERSION("0.1"); //版本
MODULE_DESCRIPTION("mykeypad_driver"); //简单的描述

View File

@ -1,11 +0,0 @@
KERN_DIR = /home/lsw/licheepi/linux-5.7.1
all:
make -C $(KERN_DIR) M=$(shell pwd) modules
clean:
make -C $(KERN_DIR) M=$(shell pwd) modules clean
rm -rf modules.order *.ko
obj-m +=sysfs_led_dev.o

View File

@ -1,141 +0,0 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <asm/io.h> //含有ioremap函数iounmap函数
#include <asm/uaccess.h> //含有copy_from_user函数和含有copy_to_user函数
#include <linux/device.h> //含有类相关的设备函数
#include <linux/cdev.h>
#include <linux/platform_device.h> //包含platform函数
#include <linux/of.h> //包含设备树相关函数
#include <linux/miscdevice.h> //包含misc相关函数
size_t *gpioe_cfg0; //存储虚拟地址到物理地址映射
size_t *gpioe_cfg1; //存储虚拟地址到物理地址映射
size_t *gpioe_data; //存储虚拟地址到物理地址映射
size_t *gpioe_pul0; //存储虚拟地址到物理地址映射
static int misc_led_open(struct inode *inode, struct file *file)
{
/* GPIOE配置 */
*((volatile size_t*)gpioe_cfg1) &= ~(7<<16); //清除配置寄存器
*((volatile size_t*)gpioe_cfg1) |= (1<<16); //配置GPIOE12为输出模式
*((volatile size_t*)gpioe_pul0) &= ~(3<<16); //清除上/下拉寄存器
*((volatile size_t*)gpioe_pul0) |= (1<<12); //配置GPIOE12为上拉模式
printk(KERN_DEBUG"open led!!!\n");
return 0;
}
static int misc_led_close(struct inode *inode, struct file *filp)
{
/* GPIOE配置 */
printk(KERN_DEBUG"close led!!!\n");
return 0;
}
static int misc_led_read(struct file *filp, char __user *buff, size_t count, loff_t *offp)
{
int ret;
size_t status = *((volatile size_t*)gpioe_data);//获取GPIOE12状态
ret = copy_to_user(buff,&status,4); //将内核空间拷贝到用户空间buff
if(ret < 0)
printk(KERN_DEBUG"read error!!!\n"); //输出信息
else
printk(KERN_DEBUG"read led ok!!!\n"); //输出信息
return 0;
}
static int misc_led_write(struct file *filp, const char __user *buff, size_t count, loff_t *offp)
{
int ret;
size_t status;
ret = copy_from_user(&status,buff,4); //将用户空间拷贝到内核空间的status
if(ret < 0)
printk(KERN_DEBUG"write error!!!\n"); //输出信息
else
printk(KERN_DEBUG"write led ok!!!\n"); //输出信息
*((volatile size_t*)gpioe_data) &= ~(1<<12) ;//清除GPIOE12状态
if(status)
*((volatile size_t*)gpioe_data) |= (1<<12);//设置GPIOE12状态1
return 0;
}
static struct file_operations misc_led_ops = {
.owner = THIS_MODULE,
.open = misc_led_open,
.read = misc_led_read,
.write = misc_led_write,
.release = misc_led_close,
};
static struct miscdevice misc_led_dev = {
.minor = MISC_DYNAMIC_MINOR, //动态分配次设备号
.name = "miscled",
.fops = &misc_led_ops, //文件操作集
};
static int misc_led_probe(struct platform_device *pdev)
{
struct resource *res;
misc_register(&misc_led_dev); //注册misc设备
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); //获取device中的GPIOE_CFG0
gpioe_cfg0 = ioremap(res->start,(res->end - res->start)+1);
res = platform_get_resource(pdev, IORESOURCE_MEM, 1); //获取device中的GPIOE_CFG1
gpioe_cfg1 = ioremap(res->start,(res->end - res->start)+1);
res = platform_get_resource(pdev, IORESOURCE_MEM, 2); //获取device中的GPIOE_DATA
gpioe_data = ioremap(res->start,(res->end - res->start)+1);
res = platform_get_resource(pdev, IORESOURCE_MEM, 3); //获取device中的GPIOE_PUL0
gpioe_pul0 = ioremap(res->start,(res->end - res->start)+1);
return 0;
}
static int misc_led_remove(struct platform_device *pdev)
{
iounmap(gpioe_cfg0); //取消GPIOE_CFG0映射
iounmap(gpioe_cfg1); //取消GPIOE_CFG1映射
iounmap(gpioe_data); //取消GPIOE_DATA映射
iounmap(gpioe_pul0); //取消GPIOE_PUL0映射
misc_deregister(&misc_led_dev); //注销misc设备
return 0;
}
static struct of_device_id misc_led_match_table[] = {
{.compatible = "lite200,misc_led",},
};
static struct platform_device_id misc_led_device_ids[] = {
{.name = "misc_led",},
};
static struct platform_driver misc_led_driver=
{
.probe = misc_led_probe,
.remove = misc_led_remove,
.driver={
.name = "misc_led",
.of_match_table = misc_led_match_table,
},
.id_table = misc_led_device_ids,
};
static int misc_led_driver_init(void)
{
platform_driver_register(&misc_led_driver);
return 0;
}
static void misc_led_driver_exit(void)
{
platform_driver_unregister(&misc_led_driver);
}
module_init(misc_led_driver_init);
module_exit(misc_led_driver_exit);
MODULE_LICENSE("GPL"); //不加的话加载会有错误提醒
MODULE_AUTHOR("1477153217@qq.com"); //作者
MODULE_VERSION("0.1"); //版本
MODULE_DESCRIPTION("misc_led_driver"); //简单的描述

View File

@ -1,141 +0,0 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <asm/io.h> //含有ioremap函数iounmap函数
#include <asm/uaccess.h> //含有copy_from_user函数和含有copy_to_user函数
#include <linux/device.h> //含有类相关的设备函数
#include <linux/cdev.h>
#include <linux/platform_device.h> //包含platform函数
#include <linux/of.h> //包含设备树相关函数
#include <linux/miscdevice.h> //包含misc相关函数
size_t *gpioe_cfg0; //存储虚拟地址到物理地址映射
size_t *gpioe_cfg1; //存储虚拟地址到物理地址映射
size_t *gpioe_data; //存储虚拟地址到物理地址映射
size_t *gpioe_pul0; //存储虚拟地址到物理地址映射
static int misc_led_open(struct inode *inode, struct file *file)
{
/* GPIOE配置 */
*((volatile size_t*)gpioe_cfg1) &= ~(7<<16); //清除配置寄存器
*((volatile size_t*)gpioe_cfg1) |= (1<<16); //配置GPIOE12为输出模式
*((volatile size_t*)gpioe_pul0) &= ~(3<<16); //清除上/下拉寄存器
*((volatile size_t*)gpioe_pul0) |= (1<<12); //配置GPIOE12为上拉模式
printk(KERN_DEBUG"open led!!!\n");
return 0;
}
static int misc_led_close(struct inode *inode, struct file *filp)
{
/* GPIOE配置 */
printk(KERN_DEBUG"close led!!!\n");
return 0;
}
static int misc_led_read(struct file *filp, char __user *buff, size_t count, loff_t *offp)
{
int ret;
size_t status = *((volatile size_t*)gpioe_data);//获取GPIOE12状态
ret = copy_to_user(buff,&status,4); //将内核空间拷贝到用户空间buff
if(ret < 0)
printk(KERN_DEBUG"read error!!!\n"); //输出信息
else
printk(KERN_DEBUG"read led ok!!!\n"); //输出信息
return 0;
}
static int misc_led_write(struct file *filp, const char __user *buff, size_t count, loff_t *offp)
{
int ret;
size_t status;
ret = copy_from_user(&status,buff,4); //将用户空间拷贝到内核空间的status
if(ret < 0)
printk(KERN_DEBUG"write error!!!\n"); //输出信息
else
printk(KERN_DEBUG"write led ok!!!\n"); //输出信息
*((volatile size_t*)gpioe_data) &= ~(1<<12) ;//清除GPIOE12状态
if(status)
*((volatile size_t*)gpioe_data) |= (1<<12);//设置GPIOE12状态1
return 0;
}
static struct file_operations misc_led_ops = {
.owner = THIS_MODULE,
.open = misc_led_open,
.read = misc_led_read,
.write = misc_led_write,
.release = misc_led_close,
};
static struct miscdevice misc_led_dev = {
.minor = MISC_DYNAMIC_MINOR, //动态分配次设备号
.name = "miscled",
.fops = &misc_led_ops, //文件操作集
};
static int misc_led_probe(struct platform_device *pdev)
{
struct resource *res;
misc_register(&misc_led_dev); //注册misc设备
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); //获取device中的GPIOE_CFG0
gpioe_cfg0 = ioremap(res->start,(res->end - res->start)+1);
res = platform_get_resource(pdev, IORESOURCE_MEM, 1); //获取device中的GPIOE_CFG1
gpioe_cfg1 = ioremap(res->start,(res->end - res->start)+1);
res = platform_get_resource(pdev, IORESOURCE_MEM, 2); //获取device中的GPIOE_DATA
gpioe_data = ioremap(res->start,(res->end - res->start)+1);
res = platform_get_resource(pdev, IORESOURCE_MEM, 3); //获取device中的GPIOE_PUL0
gpioe_pul0 = ioremap(res->start,(res->end - res->start)+1);
return 0;
}
static int misc_led_remove(struct platform_device *pdev)
{
iounmap(gpioe_cfg0); //取消GPIOE_CFG0映射
iounmap(gpioe_cfg1); //取消GPIOE_CFG1映射
iounmap(gpioe_data); //取消GPIOE_DATA映射
iounmap(gpioe_pul0); //取消GPIOE_PUL0映射
misc_deregister(&misc_led_dev); //注销misc设备
return 0;
}
static struct of_device_id misc_led_match_table[] = {
{.compatible = "lite200,misc_led",},
};
static struct platform_device_id misc_led_device_ids[] = {
{.name = "misc_led",},
};
static struct platform_driver misc_led_driver=
{
.probe = misc_led_probe,
.remove = misc_led_remove,
.driver={
.name = "misc_led",
.of_match_table = misc_led_match_table,
},
.id_table = misc_led_device_ids,
};
static int misc_led_driver_init(void)
{
platform_driver_register(&misc_led_driver);
return 0;
}
static void misc_led_driver_exit(void)
{
platform_driver_unregister(&misc_led_driver);
}
module_init(misc_led_driver_init);
module_exit(misc_led_driver_exit);
MODULE_LICENSE("GPL"); //不加的话加载会有错误提醒
MODULE_AUTHOR("1477153217@qq.com"); //作者
MODULE_VERSION("0.1"); //版本
MODULE_DESCRIPTION("misc_led_driver"); //简单的描述

View File

@ -1,100 +0,0 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <asm/io.h> //含有ioremap函数iounmap函数
#include <asm/uaccess.h> //含有copy_from_user函数和含有copy_to_user函数
#include <linux/device.h> //含有类相关的设备函数
#include <linux/cdev.h>
#include <linux/kobject.h> //包含sysfs文件系统对象类
#include <linux/sysfs.h> //包含sysfs操作文件函数
#include <linux/slab.h>
#include <linux/string.h>
#define GPIOE_CFG0 (0x01C20890)
#define GPIOE_CFG1 (0x01C20894)
#define GPIOE_DATA (0x01C208A0)
#define GPIOE_PUL0 (0x01C208AC)
size_t *gpioe_cfg0; //存储虚拟地址到物理地址映射
size_t *gpioe_cfg1; //存储虚拟地址到物理地址映射
size_t *gpioe_data; //存储虚拟地址到物理地址映射
size_t *gpioe_pul0; //存储虚拟地址到物理地址映射
static int led_status = 0; //定义一个led状态变量
static struct kobject *led_kobj; //定义一个led_kobj
static ssize_t led_show(struct kobject* kobjs,struct kobj_attribute *attr,char *buf)
{
printk(KERN_INFO "Read led\n");
return sprintf(buf,"The led_status status is = %d\n",led_status);
}
static ssize_t led_store(struct kobject *kobj, struct kobj_attribute *attr,const char *buf, size_t count)
{
printk(KERN_INFO "led status store\n");
if(0 == memcmp(buf,"on",2))
{
*((volatile size_t*)gpioe_data) &= ~(1<<12) ;//清除GPIOE12状态
led_status = 1;
}
else if(0 == memcmp(buf,"off",3))
{
*((volatile size_t*)gpioe_data) |= (1<<12);//设置GPIOE12状态1
led_status = 0;
}
else
{
printk(KERN_INFO "Not support cmd\n");
}
return count;
}
//定义一个led_attr对象属性
static struct kobj_attribute led_attr = __ATTR(led_status,0660,led_show,led_store);
static int __init sysfs_led_init(void)
{
int ret;
led_kobj = kobject_create_and_add("sys_led",NULL);
if(led_kobj == NULL)
{
printk(KERN_INFO"create led_kobj failed!\n");
return -1;
}
ret = sysfs_create_file(led_kobj, &led_attr.attr);
if(ret != 0)
{
printk(KERN_INFO"create sysfa file failed!\n");
return -1;
}
gpioe_cfg0 = ioremap(GPIOE_CFG0,4); //将GPIOE_CFG0物理地址映射为虚拟地址
gpioe_cfg1 = ioremap(GPIOE_CFG1,4); //将GPIOE_CFG1物理地址映射为虚拟地址
gpioe_data = ioremap(GPIOE_DATA,4); //将GPIOE_DATA物理地址映射为虚拟地址
gpioe_pul0 = ioremap(GPIOE_PUL0,4); //将GPIOE_PUL0物理地址映射为虚拟地址
*((volatile size_t*)gpioe_cfg1) &= ~(7<<16); //清除配置寄存器
*((volatile size_t*)gpioe_cfg1) |= (1<<16); //配置GPIOE12为输出模式
*((volatile size_t*)gpioe_pul0) &= ~(3<<16); //清除上/下拉寄存器
*((volatile size_t*)gpioe_pul0) |= (1<<12); //配置GPIOE12为上拉模式
*((volatile size_t*)gpioe_data) &= ~(1<<12) ;//清除GPIOE12状态
return 0;
}
static void __exit sysfs_led_exit(void)
{
sysfs_remove_file(led_kobj,&led_attr.attr); //删除属性
kobject_put(led_kobj); //删除对象
printk(KERN_INFO "Goodbye!\n");
}
module_init(sysfs_led_init);
module_exit(sysfs_led_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("1477153217@qq.com");
MODULE_DESCRIPTION("sysfs led");
MODULE_VERSION("0.1");

View File

@ -1,11 +0,0 @@
KERN_DIR = /home/lsw/licheepi/linux-5.7.1
all:
make -C $(KERN_DIR) M=$(shell pwd) modules
clean:
make -C $(KERN_DIR) M=$(shell pwd) modules clean
rm -rf modules.order *.ko
obj-m += at24c02.o

View File

@ -1,123 +0,0 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <asm/io.h> //含有ioremap函数iounmap函数
#include <asm/uaccess.h> //含有copy_from_user函数和含有copy_to_user函数
#include <linux/device.h> //含有类相关的设备函数
#include <linux/cdev.h>
#include <linux/platform_device.h> //包含platform函数
#include <linux/of.h> //包含设备树相关函数
#include <linux/i2c.h>
#include <linux/kobject.h> //包含sysfs文件系统对象类
#include <linux/sysfs.h> //包含sysfs操作文件函数
#include <linux/regmap.h>
static int recv[16] = {0}; //保存接收数据
static struct kobject *at24c02_kobj; //定义一个led_kobj
static struct regmap *at24c02_regmap;
static const struct regmap_config at24c02_config =
{
.reg_bits = 8, //寄存器8位
.val_bits = 8, //数据8位
.max_register = 255, //最大寄存器255个
.cache_type = REGCACHE_NONE, //不使用cache
.volatile_reg = false,
};
static ssize_t at24c02_show(struct kobject* kobjs,struct kobj_attribute *attr,char *buf)
{
int ret;
ret = regmap_write(at24c02_regmap,0x01,0); //先发写地址操作
if(ret)
{
printk(KERN_ERR"write addr failed!\n");
return ret;
}
ret = regmap_read(at24c02_regmap,0x01,&recv[0]); //然后发读数据操作
if(ret)
{
printk(KERN_ERR"read addr failed!\n");
return ret;
}
return sprintf(buf,"read status register=0x%x\n",recv[0]);
}
static ssize_t at24c02_store(struct kobject *kobj, struct kobj_attribute *attr,const char *buf, size_t count)
{
int ret;
ret = regmap_write(at24c02_regmap,0x01,0x2f);//写一个字节数据0x2f
if(!ret)
{
printk(KERN_ERR"write data failed!\n");
}
return count;
}
static struct kobj_attribute at24c02_attr = __ATTR(at24c02_dev,0660,at24c02_show,at24c02_store);
static int at24c02_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
int ret;
at24c02_kobj = kobject_create_and_add("sys_at24c02",NULL);
if(at24c02_kobj == NULL)
{
printk(KERN_INFO"create at24c02_kobj failed!\n");
return -1;
}
ret = sysfs_create_file(at24c02_kobj, &at24c02_attr.attr);
if(ret != 0)
{
printk(KERN_INFO"create at24c02_dev file failed!\n");
return -1;
}
at24c02_regmap = regmap_init_i2c(client,&at24c02_config);
return 0;
}
static int at24c02_remove(struct i2c_client *client)
{
sysfs_remove_file(at24c02_kobj, &at24c02_attr.attr); //删除属性
kobject_put(at24c02_kobj); //删除对象
regmap_exit(at24c02_regmap);
printk(KERN_INFO "exit sysfs at24c02!\n");
return 0;
}
static const struct i2c_device_id at24c02_id[] = {
{ "test,at24c0x", 0 },
{ }
};
static const struct of_device_id at24c02_of_match[] = {
{ .compatible = "test,at24c0x"},
{ },
};
MODULE_DEVICE_TABLE(of, at24c02_of_match);
static struct i2c_driver at24c02_driver = {
.driver = {
.name = "test,at24c0x",
.owner = THIS_MODULE,
.of_match_table = at24c02_of_match,
},
.probe = at24c02_probe,
.remove = at24c02_remove,
.id_table = at24c02_id,
};
module_i2c_driver(at24c02_driver);
MODULE_LICENSE("GPL"); //不加的话加载会有错误提醒
MODULE_AUTHOR("1477153217@qq.com"); //作者
MODULE_VERSION("0.1"); //版本
MODULE_DESCRIPTION("at24c02_driver"); //简单的描述

View File

@ -1,11 +0,0 @@
KERN_DIR = /home/lsw/licheepi/linux-5.7.1
all:
make -C $(KERN_DIR) M=$(shell pwd) modules
clean:
make -C $(KERN_DIR) M=$(shell pwd) modules clean
rm -rf modules.order *.ko
obj-m +=w25q128.o

View File

@ -1,115 +0,0 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <asm/io.h> //含有ioremap函数iounmap函数
#include <asm/uaccess.h> //含有copy_from_user函数和含有copy_to_user函数
#include <linux/device.h> //含有类相关的设备函数
#include <linux/cdev.h>
#include <linux/platform_device.h> //包含platform函数
#include <linux/of.h> //包含设备树相关函数
#include <linux/spi/spi.h>
#include <linux/kobject.h> //包含sysfs文件系统对象类
#include <linux/sysfs.h> //包含sysfs操作文件函数
#define ERASE_OPCODE 0x20 //擦除操作码
#define R_STS_OPCODE 0x35 //读状态操作码
static char tx_data[16] = {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};
static char rx_data[16] = {0};
static struct kobject *w25qxx_kobj; //定义一个led_kobj
struct spi_transfer xfer;
struct spi_device *w25qxx_spi; //保存spi设备结构体
static ssize_t w25qxx_show(struct kobject* kobjs,struct kobj_attribute *attr,char *buf)
{
return sprintf(buf,"read status register=%d\n",rx_data[0]);
}
static ssize_t w25qxx_store(struct kobject *kobj, struct kobj_attribute *attr,const char *buf, size_t count)
{
int ret;
int erase_addr=0x123456;
tx_data[0]=ERASE_OPCODE;
tx_data[1]=(erase_addr>>16)&0xff;
tx_data[2]=(erase_addr>>8)&0xff;
tx_data[3]=(erase_addr)&0xff;
xfer.len = 4;
ret = spi_sync_transfer(w25qxx_spi,&xfer,1); //擦除操作
if(ret)
{
printk(KERN_INFO"erase w25q128 failed!\n");
}
tx_data[0]=R_STS_OPCODE;
ret = spi_write_then_read(w25qxx_spi,tx_data,1,rx_data,1);
return count;
}
static struct kobj_attribute w25qxx_attr = __ATTR(w25q128_dev,0660,w25qxx_show,w25qxx_store);
static void w25qxx_init(void)
{
xfer.tx_buf = tx_data;
xfer.rx_buf = rx_data;
xfer.len = sizeof(tx_data);
xfer.bits_per_word = 8;
memset(rx_data,0,16);
}
static int w25qxx_probe(struct spi_device *spi)
{
int ret;
w25qxx_kobj = kobject_create_and_add("sys_w25qxx",NULL);
if(w25qxx_kobj == NULL)
{
printk(KERN_INFO"create w25qxx_kobj failed!\n");
return -1;
}
ret = sysfs_create_file(w25qxx_kobj, &w25qxx_attr.attr);
if(ret != 0)
{
printk(KERN_INFO"create w25q128_dev file failed!\n");
return -1;
}
w25qxx_spi = spi_dev_get(spi);
w25qxx_init();
return 0;
}
static int w25qxx_remove(struct spi_device *spi)
{
sysfs_remove_file(w25qxx_kobj, &w25qxx_attr.attr); //删除属性
kobject_put(w25qxx_kobj); //删除对象
printk(KERN_INFO "exit sysfs w25qxx!\n");
return 0;
}
static struct of_device_id w25qxx_match_table[] = {
{.compatible = "test,w25qxx",},
};
static struct spi_device_id w25qxx_ids[] = {
{.name = "w25q128",},
};
static struct spi_driver w25qxx_cdev = {
.driver = {
.name = "w25qxx",
.owner = THIS_MODULE,
.of_match_table = w25qxx_match_table,
},
.probe = w25qxx_probe,
.remove = w25qxx_remove,
.id_table = w25qxx_ids,
};
module_spi_driver(w25qxx_cdev);
MODULE_LICENSE("GPL"); //不加的话加载会有错误提醒
MODULE_AUTHOR("1477153217@qq.com"); //作者
MODULE_VERSION("0.1"); //版本
MODULE_DESCRIPTION("w25qxx_driver"); //简单的描述

View File

@ -1,11 +0,0 @@
KERN_DIR = /home/lsw/licheepi/linux-5.7.1
all:
make -C $(KERN_DIR) M=$(shell pwd) modules
clean:
make -C $(KERN_DIR) M=$(shell pwd) modules clean
rm -rf modules.order *.ko
obj-m +=led_dev.o

View File

@ -1,140 +0,0 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <asm/io.h> //含有ioremap函数iounmap函数
#include <asm/uaccess.h> //含有copy_from_user函数和含有copy_to_user函数
#include <linux/device.h> //含有类相关的设备函数
#include <linux/cdev.h>
#define GPIOE_CFG0 (0x01C20890)
#define GPIOE_CFG1 (0x01C20894)
#define GPIOE_DATA (0x01C208A0)
#define GPIOE_PUL0 (0x01C208AC)
static dev_t led_dev_num; //定义一个设备号
static struct cdev *led_dev; //定义一个设备管理结构体指针
static struct class *led_class; //定义一个设备类
static struct device *led0; //定义一个设备
size_t *gpioe_cfg0; //存储虚拟地址到物理地址映射
size_t *gpioe_cfg1; //存储虚拟地址到物理地址映射
size_t *gpioe_data; //存储虚拟地址到物理地址映射
size_t *gpioe_pul0; //存储虚拟地址到物理地址映射
static int led_open(struct inode *inode, struct file *file)
{
/* GPIOE配置 */
*((volatile size_t*)gpioe_cfg1) &= ~(7<<16); //清除配置寄存器
*((volatile size_t*)gpioe_cfg1) |= (1<<16); //配置GPIOE12为输出模式
*((volatile size_t*)gpioe_pul0) &= ~(3<<16); //清除上/下拉寄存器
*((volatile size_t*)gpioe_pul0) |= (1<<12); //配置GPIOE12为上拉模式
*((volatile size_t*)gpioe_data) &= ~(1<<16); //清除数据寄存器
printk(KERN_DEBUG"open led!!!\n");
return 0;
}
static int led_close(struct inode *inode, struct file *filp)
{
/* GPIOE配置 */
*((volatile size_t*)gpioe_cfg1) &= ~(7<<16); //清除配置寄存器
*((volatile size_t*)gpioe_cfg1) |= (7<<16); //配置GPIOE12为输出模式
*((volatile size_t*)gpioe_pul0) &= ~(3<<16); //清除上/下拉寄存器
*((volatile size_t*)gpioe_data) &= ~(1<<16); //清除数据寄存器
printk(KERN_DEBUG"close led!!!\n");
return 0;
}
static int led_read(struct file *filp, char __user *buff, size_t count, loff_t *offp)
{
int ret;
size_t status = *((volatile size_t*)gpioe_data);//获取GPIOE12状态
ret = copy_to_user(buff,&status,4); //将内核空间拷贝到用户空间buff
if(ret < 0)
printk(KERN_DEBUG"read error!!!\n"); //输出信息
else
printk(KERN_DEBUG"read led ok!!!\n"); //输出信息
return 0;
}
static int led_write(struct file *filp, const char __user *buff, size_t count, loff_t *offp)
{
int ret;
size_t status;
ret = copy_from_user(&status,buff,4); //将用户空间拷贝到内核空间的status
if(ret < 0)
printk(KERN_DEBUG"write error!!!\n"); //输出信息
else
printk(KERN_DEBUG"write led ok!!!\n"); //输出信息
*((volatile size_t*)gpioe_data) = status;//设置GPIOE12状态
return 0;
}
static struct file_operations led_ops = {
.owner = THIS_MODULE,
.open = led_open,
.read = led_read,
.write = led_write,
.release = led_close,
};
static int __init led_init(void)
{
int ret;
led_dev = cdev_alloc(); //动态申请一个设备结构体
if(led_dev == NULL)
{
goto error;
}
ret = alloc_chrdev_region(&led_dev_num,0,1,"led"); //动态申请一个设备号
if(ret == 0)
{
goto error;
}
led_dev->owner = THIS_MODULE; //初始化设备管理结构体的owner为THIS_MODULE
led_dev->ops = &led_ops; //初始化设备操作函数指针为led_ops函数
cdev_add(led_dev,led_dev_num,1); //将设备添加到内核中
led_class = class_create(THIS_MODULE, "led_class"); //创建一个类
if(led_class == NULL)
{
goto error;
}
led0 = device_create(led_class,NULL,led_dev_num,NULL,"led0"); //创建一个设备
if(IS_ERR(led0))
{
goto error;
}
gpioe_cfg0 = ioremap(GPIOE_CFG0,4); //将GPIOE_CFG0物理地址映射为虚拟地址
gpioe_cfg1 = ioremap(GPIOE_CFG1,4); //将GPIOE_CFG1物理地址映射为虚拟地址
gpioe_data = ioremap(GPIOE_DATA,4); //将GPIOE_DATA物理地址映射为虚拟地址
gpioe_pul0 = ioremap(GPIOE_PUL0,4); //将GPIOE_PUL0物理地址映射为虚拟地址
return 0;
error:
printk(KERN_WARNING"led_init failed!\n");
return 1;
}
static void __exit led_exit(void)
{
cdev_del(led_dev); //从内核中删除设备管理结构体
unregister_chrdev_region(led_dev_num,1); //注销设备号
device_destroy(led_class,led_dev_num); //删除设备节点
class_destroy(led_class); //删除设备类
iounmap(gpioe_cfg0); //取消GPIOE_CFG0映射
iounmap(gpioe_cfg1); //取消GPIOE_CFG1映射
iounmap(gpioe_data); //取消GPIOE_DATA映射
iounmap(gpioe_pul0); //取消GPIOE_PUL0映射
}
module_init(led_init);
module_exit(led_exit);
MODULE_LICENSE("GPL"); //不加的话加载会有错误提醒
MODULE_AUTHOR("1477153217@qq.com"); //作者
MODULE_VERSION("0.1"); //版本
MODULE_DESCRIPTION("led_dev"); //简单的描述