当前位置:   article > 正文

ZYNQ 开发平台 Linux驱动-控制AXI GPIO外设_zynq 控制gpio代码

zynq 控制gpio代码

以下是加了注释的Linux驱动程序代码,用于控制AXI GPIO外设:


```c

```c
  • 1
  • 2
  • 3
  • 4

#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/gpio.h>
#include <asm/uaccess.h>

//GPIO的管脚号,此处为对应LED的管脚号
#define GPIO_LED 54

//设备驱动程序的名称
#define DEVICE_NAME “axi-gpio-driver”

//保存设备文件的主设备号
static int Major;

//定义设备文件的读函数
static ssize_t read_gpio(struct file *f, char __user *buf, size_t count, loff_t *offset)
{
//定义缓冲区
char val[2];

//读取GPIO的电平值
gpio_get_value(GPIO_LED, &val);

//将获得的电平值写入缓冲区
val[1] = '\n';
if (val[0] == 0)
    val[0] = '0';
else
    val[0] = '1';

//将缓冲区的数据拷贝到用户空间的缓冲区
copy_to_user(buf, val, 2);

//返回缓冲区的大小(此处为2)
return 2;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

}

//定义设备文件的写函数
static ssize_t write_gpio(struct file *f, const char __user *buf, size_t count, loff_t *offset)
{
//定义缓冲区
char val[2];

//将用户空间的缓冲区拷贝到设备驱动程序的缓冲区
copy_from_user(val, buf, count);

//设置GPIO的电平值
if (val[0] == '0')
    gpio_set_value(GPIO_LED,0);
else if (val[0] == '1')
    gpio_set_value(GPIO_LED,1);

//返回缓冲区的大小(此处为count)
return count;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

}

//定义设备文件的操作函数结构体
static struct file_operations gpio_fops =
{
.owner = THIS_MODULE,
.read = read_gpio,
.write = write_gpio,
};

//设备驱动程序的初始化函数
static int __init gpio_init(void)
{
//申请GPIO资源
if (gpio_request(GPIO_LED, “LED”) < 0)
{
printk(KERN_ALERT “gpio_request failure\n”);
return -1;
}

//设置GPIO为输出模式,初始值为0(关灯)
if (gpio_direction_output(GPIO_LED, 0) < 0)
{
    printk(KERN_ALERT "gpio_direction_output failure\n");
    return -1;
}

//注册设备文件
Major = register_chrdev(0, DEVICE_NAME, &gpio_fops);
if (Major < 0)
{
    printk(KERN_ALERT "register_chrdev failure\n");
    return Major;
}

printk(KERN_ALERT "axi-gpio-driver module is loaded\n");

return 0;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

}

//设备驱动程序的卸载函数
static void __exit gpio_exit(void)
{
//释放GPIO资源
gpio_free(GPIO_LED);

//注销设备文件
unregister_chrdev(Major, DEVICE_NAME);

printk(KERN_ALERT "axi-gpio-driver module is unloaded\n");
  • 1
  • 2
  • 3
  • 4

}

//模块的初始化函数和卸载函数
module_init(gpio_init);
module_exit(gpio_exit);

//模块的说明信息
MODULE_LICENSE(“GPL”);
MODULE_AUTHOR(“Your Name”);
MODULE_DESCRIPTION(“A simple GPIO device driver for AXI GPIO on Zynq”);



注释详解如下: 

- 申请头文件
  • 1
  • 2
  • 3
  • 4
  • 5

#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/gpio.h>
#include <asm/uaccess.h>

这里引入了一些Linux内核的头文件,它们的作用如下:
    - <linux/init.h>:包含模块的初始化和清理函数宏定义。
    - <linux/module.h>:包含模块定义和其他必要的宏、类和函数的声明和定义。
    - <linux/kernel.h>:包含各种内核需要的常量和函数的声明。
    - <linux/fs.h>:包含了文件系统相关的宏、类型定义等标准头文件。
    - <linux/gpio.h>:包含了GPIO的宏定义和相关函数的声明。
    - <asm/uaccess.h>:包含了访问用户空间缓冲区的函数等

- 定义GPIO管脚号 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

#define GPIO_LED 54

这里定义了一个宏变量GPIO_LED保存LED的管脚号54,方便后面使用。

- 定义设备的名称 
  • 1
  • 2
  • 3

#define DEVICE_NAME “axi-gpio-driver”

这里定义了一个字符串变量DEVICE_NAME保存设备的名称,用于生成设备文件。

- 保存主设备号 
  • 1
  • 2
  • 3

static int Major;

这里定义了一个静态变量Major,保存主设备号。

- 定义设备文件的读函数 
  • 1
  • 2
  • 3

static ssize_t read_gpio(struct file *f, char __user *buf, size_t count, loff_t *offset)

这里定义了read_gpio函数,用于从设备文件中读取GPIO的电平值。它有4个参数,分别是:
    - struct file *f:文件操作对象
    - char __user *buf:指向用户空间缓冲区的指针
    - size_t count:缓冲区的大小
    - loff_t *offset:文件读取的偏移量

- 定义设备文件的写函数 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

static ssize_t write_gpio(struct file *f, const char __user *buf, size_t count, loff_t *offset)

这里定义了write_gpio函数,用于向设备文件中写入GPIO的电平值。它有4个参数,分别是:
    - struct file *f:文件操作对象
    - const char __user *buf:指向用户空间缓冲区的指针
    - size_t count:缓冲区的大小
    - loff_t *offset:文件写入的偏移量

- 定义设备文件的操作函数结构体 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

static struct file_operations gpio_fops =
{
.owner = THIS_MODULE,
.read = read_gpio,
.write = write_gpio,
};

定义了一个静态变量gpio_fops,它是一个struct file_operations类型的结构体,定义了文件操作对象的设备函数表,它包含3个设备函数:读、写和设备打开时的操作。

- 定义设备驱动程序的初始化函数 
  • 1
  • 2
  • 3

static int __init gpio_init(void)

该函数用于初始化设备驱动程序(安装设备驱动程序),它没有参数。

- 申请GPIO资源 
  • 1
  • 2
  • 3

if (gpio_request(GPIO_LED, “LED”) < 0)
{
printk(KERN_ALERT “gpio_request failure\n”);
return -1;
}

该函数使用gpio_request()函数请求GPIO资源,如果请求失败,打印一个错误信息,并返回-1。

- 设置GPIO为输出模式,初始值为0(关灯) 
  • 1
  • 2
  • 3

if (gpio_direction_output(GPIO_LED, 0) < 0)
{
printk(KERN_ALERT “gpio_direction_output failure\n”);
return -1;
}

这里通过gpio_direction_output()函数设置GPIO为输出模式,初始值为0(关灯)。如果设置失败,打印一个错误信息,并返回-1。

- 注册设备文件 
  • 1
  • 2
  • 3

Major = register_chrdev(0, DEVICE_NAME, &gpio_fops);
if (Major < 0)
{
printk(KERN_ALERT “register_chrdev failure\n”);
return Major;
}

该函数调用register_chrdev()函数注册字符设备,成功后返回设备文件的主设备号(Major),同时保存文件操作对象的设备函数表,如果注册失败则返回错误号,打印一个错误信息,并结束函数执行。

- 设备驱动程序的卸载函数 
  • 1
  • 2
  • 3

static void __exit gpio_exit(void)

该函数用于卸载设备驱动程序(卸载设备驱动程序),它没有参数。

- 释放GPIO资源 
  • 1
  • 2
  • 3

gpio_free(GPIO_LED);

该函数使用gpio_free()函数释放GPIO资源,将GPIO管脚号设置为对应的管脚,释放占用的资源。

- 注销设备文件 
  • 1
  • 2
  • 3

unregister_chrdev(Major, DEVICE_NAME);

该函数使用unregister_chrdev()函数注销字符设备,同时释放占用的资源。

- 设备驱动程序的初始化函数和卸载函数 
  • 1
  • 2
  • 3

module_init(gpio_init);
module_exit(gpio_exit);

这两行代码分别调用设备驱动程序的初始化函数和卸载函数,用于加载或卸载设备驱动程序。

- 模块的说明信息 
  • 1
  • 2
  • 3

MODULE_LICENSE(“GPL”);
MODULE_AUTHOR(“Your Name”);
MODULE_DESCRIPTION(“A simple GPIO device driver for AXI GPIO on Zynq”);

这几行是设备驱动程序的说明信息,包括了许可证、作者和一些基本描述。模块的许可证、作者和描述等信息,将会在模块被加载时在控制台上显示。
  • 1
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Li_阴宅/article/detail/744648
推荐阅读
相关标签
  

闽ICP备14008679号