- 2024-08-22
-
发表了主题帖:
of_iomap函数在内核中返回值是NULL,这是怎么通过函数返回值得到映射后的地址的?
如图,of_iomap函数的返回值一直是NULL,但是看网上的使用方法是将该函数的返回值作为设备树中的reg的值,那么这个函数的返回的不就是空指针了吗?
- 2024-07-28
-
回复了主题帖:
为什么我做出来的驱动无法使用echo对设备进行控制呢?
本帖最后由 seven_spark 于 2024-7-28 10:20 编辑
就是GPIO的驱动,我没有参照现成的,没有使用设备树,为什么这种方式不行呢?
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
/*
头文件,是与芯片物理属性相关的,寄存器值
*/
#define CCM_CCGR1_BASE (0X020C406C)
#define SW_MUX_GPIO1_IO03_BASE (0X020E0068)
#define SW_PAD_GPIO1_IO03_BASE (0X020E02F4)
#define GPIO1_DR_BASE (0X0209C000)
#define GPIO1_GDIR_BASE (0X0209C004)
/*
虚实映射的地址,是虚拟地址
*/
static void __iomem *IMX6U_CCM_CCGR1;
static void __iomem *SW_MUX_GPIO1_IO03;
static void __iomem *SW_PAD_GPIO1_IO03;
static void __iomem *GPIO1_DR;
static void __iomem *GPIO1_GDIR;
/*
宏定义
*/
#define LED_NAME "led_us"
#define LEDOFF 0
#define LEDON 1
#define LED_NUM 1
static struct led_st
{
int major;
int minor;
int num;
char *name;
dev_t devno;
struct cdev cdev;
struct class *cls;
struct device *dvs;
unsigned char buf[1];
};
static struct led_st *led = NULL;
static void led_switch(unsigned char sta)
{
unsigned int val = 0;
if(sta == LEDON)
{
val = readl(GPIO1_DR);//GPIO_DR是控制电平的寄存器
val &= ~(1 i_cdev, struct led_st, cdev));
return 0;
}
static ssize_t led_read(struct file *filp, char __user *buf, size_t cnt, loff_t *offt)
{
return 0;
}
static ssize_t led_write(struct file *pfilp, const char __user *buf, size_t cnt, loff_t *offt)
{
int retvalue;
unsigned char ledstat;
struct led_st *ptemp = (struct led_st *)pfilp->private_data;
retvalue = copy_from_user(ptemp->buf, buf, cnt);
if(retvalue < 0)
{
printk("kernel write failed.\n");
return -EFAULT;
}
ledstat = ptemp->buf[0];
if(ledstat == LEDON)
{
led_switch(LEDON);
}
else if(ledstat == LEDOFF)
{
led_switch(LEDOFF);
}
else
{
return -EFAULT;
}
*offt += cnt;
return cnt;
}
static int led_release(struct inode *inode, struct file *filp)
{
return 0;
}
static struct file_operations led_fops =
{
.owner = THIS_MODULE,
.open = led_open,
.read = led_read,
.write = led_write,
.release = led_release,
};
static int __init led_init(void)
{
int val = 0;
led = kzalloc(sizeof(struct led_st), GFP_KERNEL);
if(NULL == led)
{
printk("led kzalloc failed\n");
return -1;
}
else
{
led->major = 0;
led->minor = 0;
led->num = LED_NUM;
led->name = LED_NAME;
}
IMX6U_CCM_CCGR1 = ioremap(CCM_CCGR1_BASE, 4);
SW_MUX_GPIO1_IO03 = ioremap(SW_MUX_GPIO1_IO03_BASE, 4);
SW_PAD_GPIO1_IO03 = ioremap(SW_PAD_GPIO1_IO03_BASE, 4);
GPIO1_DR = ioremap(GPIO1_DR_BASE, 4);
GPIO1_GDIR = ioremap(GPIO1_GDIR_BASE, 4);
val = readl(IMX6U_CCM_CCGR1);
val &= ~(3 cdev), led->devno, led->num))
{
unregister_chrdev_region(led->devno, led->num);
printk("cdev add failed\n");
return -2;
}
}
led->cls = class_create(THIS_MODULE, led->name);
if(led->cls == NULL)
{
printk("class create failed\n");
cdev_del(&(led->cdev));
unregister_chrdev_region(led->devno, led->num);
return -3;
}
led->dvs = device_create(led->cls, NULL, led->devno, NULL, led->name);
if(led->dvs == NULL)
{
printk("device create failed\n");
class_destroy(led->cls);
cdev_del(&(led->cdev));
unregister_chrdev_region(led->devno, led->num);
return -4;
}
return 0;
}
static void __exit led_exit(void)
{
iounmap(IMX6U_CCM_CCGR1);
iounmap(SW_MUX_GPIO1_IO03);
iounmap(SW_PAD_GPIO1_IO03);
iounmap(GPIO1_DR);
iounmap(GPIO1_GDIR);
device_destroy(led->cls, led->devno);
class_destroy(led->cls);
cdev_del(&(led->cdev));
unregister_chrdev_region(led->devno, led->num);
led = NULL;
}
module_init(led_init);
module_exit(led_exit);
MODULE_LICENSE("GPL");
- 2024-07-27
-
发表了主题帖:
为什么我做出来的驱动无法使用echo对设备进行控制呢?
我编写了一个LED的驱动程序,为什么我无法使用echo 的方式对该设备节点进行写呢?驱动模块的处理流程是在init中先alloc_chrdev_region后,使用cdev_init初始化cdev,然后使用cdev_add将file_operations的操作函数添加到字符设备中,再使用class_create和device_create。该流程有啥问题吗?有没有知道这原因的大佬帮忙指点一下。。
-
发表了主题帖:
芯片端驱动和设备端驱动的区别?我这样理解对吗?
芯片端驱动和设备端驱动的区别在哪里呢?一直都是说芯片端驱动是芯片厂家写好了的,可以这样理解吗?比如i2c驱动一个温度传感器的话,芯片端的i2c驱动就是配置i2c控制器的寄存器,如设置速率等,设备端驱动就是按照温度传感器的数据手册写出read和write函数。又比方说stm32的话,库函数是不是就相当于是芯片端驱动了?