全志A33 linux led驱动编程(附实测参考代码)

简介: 开发平台 * 芯灵思SinlinxA33开发板 实验原理 在芯灵思开发板上,没有led灯模块,只能通过引脚电平观察: 这里我选择LS-INT引脚。 全志A33一共有10组IO口,每组IO有9个相关功能控制器,LS-INT属于PB7,相关寄存器如图 本次实验只用到这两个寄存器,在程序中命名为gpio_con,gpio_dat ,设置为输出引脚。

开发平台

*  芯灵思SinlinxA33开发板

淘宝店铺: https://sinlinx.taobao.com/

image

嵌入式linux 开发板交流 QQ:641395230

实验原理

image

在芯灵思开发板上,没有led灯模块,只能通过引脚电平观察: 这里我选择LS-INT引脚。

全志A33一共有10组IO口,每组IO有9个相关功能控制器,LS-INT属于PB7,相关寄存器如图

本次实验只用到这两个寄存器,在程序中命名为gpio_con,gpio_dat ,设置为输出引脚。

  • 1)注册 class_register(class) 将class注册到内核中。调用前,必须手动分配class内存;调用后必须设置class的name等参数注册 class_create(owner,name) 创建class并将class注册到内核中。返回值为class结构体指针。注销 void class_unregister(struct class cls) 注销class,与class_register()配对使用。注销void class_destroy(struct class cls) 注销class,与class_create()配对使用内核中定义了struct class结构体顾名思义,一个struct class结构体类型变量对应一个类,内核同时提供了class_create(…)函数,可以用它来创建一个类,这个类存放于sysfs下面,一旦创建好了这个类,再调用device_create(…)函数来在/dev目录下创建相应的设备节点。这样,加载模块的时候,用户空间中的udev会自动响应device_create(…)函数,去/sysfs下寻找对应的类从而创建设备节点.
  • 2)void ioremap(unsigned long phys_addr , unsigned long size , unsigned long flags)用mmap映射一个设备意味着使用户空间的一段地址关联到设备内存上,这使得只要程序在分配的地址范围内进行读取或写入实际上就是对设备的访问。解除映射void iounmap(void addr)//取消ioremap所映射的IO地址
  • 3)register_chrdev(unsigned int major, const char name,const struct file_operations fops);
    但其实这个函数是linux版本2.4之前的注册方式,它的原理是:

    • (1)确定一个主设备号,如果major=0,则会自动分配设备号
    • (2)构造一个file_operations结构体, 然后放在chrdevs数组中
    • (3)注册:register_chrdev,cat /proc/devices查看内核中已经注册过的字符设备驱动(和块设备驱动),注意这里并不是驱动文件设备节点!
  • 4) Linux使用file_operations结构访问驱动程序的函数,这个结构的每一个成员的名字都对应着一个调用
  • 5) class_device_create() 调用class_create为该设备创建一个class,再为每个设备调用 class_device_create创建对应的设备。大致用法如下:struct class *myclass = class_create(THIS_MODULE, “my_device_driver”);class_device_create(myclass, NULL, MKDEV(major_num, 0), NULL, “my_device”);这样的module被加载时,udev daemon就会自动在/dev下创建my_device设备件。

总体代码框架

1)先要有file_operations先要有引脚初始化函数myled_init(void),在myled_init里面注册class并将class类注册到内核中
创建设备节点,初始化引脚已经将寄存器地址映射到虚拟内存中,最后调用module_init(myled_init)驱动的加载就靠它
2)创建这个file_operations结构体
    static struct file_operations myled_oprs = {
    .owner = THIS_MODULE,
    .open  = led_open,
    .write = led_write,
    .release = led_release,
    }; 
下面就围绕这个结构体写函数led_write() led_open() led_release()
3)最后要注销设备

附实测代码,参考下

LED驱动代码:

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/uaccess.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/of_platform.h>
static int major;
static struct class *led_class;
volatile unsigned long *gpio_con = NULL;
volatile unsigned long *gpio_dat = NULL;
static int led_open (struct inode *node, struct file *filp)
{
    /* PB7 - 0x01C20824 */
   if (gpio_con) {
        printk("ioremap  0x%x\n", gpio_con);
        }
        else {
            return -EINVAL;
        }
    return 0;
}

static ssize_t led_write (struct file *filp, const char __user *buf, size_t size, loff_t *off)
{
     unsigned char val;        
     copy_from_user(&val, buf, 1);

        if (val)
        {
             *gpio_dat |= (1<<7);
        }
        else
        {
                 *gpio_dat &= ~(1<<7);
        }

        return 1; 
}

static int led_release (struct inode *node, struct file *filp)
{
    printk("iounmap(0x%x)\n", gpio_con);
    iounmap(gpio_con);
    return 0;
}


static struct file_operations myled_oprs = {
    .owner = THIS_MODULE,
    .open  = led_open,
    .write = led_write,
    .release = led_release,
};
static int myled_init(void)
{
   major = register_chrdev(0, "myled", &myled_oprs);
   led_class = class_create(THIS_MODULE, "myled");
   device_create(led_class, NULL, MKDEV(major, 0), NULL, "ledzzzzzzzz"); 
   gpio_con = (volatile unsigned long *)ioremap(0x01C20824, 1);   //0x01C20824
   gpio_dat = gpio_con + 4;     //0x01C20834        
   *gpio_con &= ~(7<<28);
   *gpio_con |=  (1<<28);
   *gpio_dat &= ~(1<<7);
   return 0;
}

APP代码:

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/uaccess.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/of_platform.h>
static int major;
static struct class *led_class;
volatile unsigned long *gpio_con = NULL;
volatile unsigned long *gpio_dat = NULL;
static int led_open (struct inode *node, struct file *filp)
{
    /* PB7 - 0x01C20824 */
   if (gpio_con) {
                printk("ioremap  0x%x\n", gpio_con);
        }
        else {
                return -EINVAL;
        }
    return 0;
}

static ssize_t led_write (struct file *filp, const char __user *buf, size_t size, loff_t *off)
{
     unsigned char val;        
     copy_from_user(&val, buf, 1);

        if (val)
        {
                 *gpio_dat |= (1<<7);
        }
        else
        {
             *gpio_dat &= ~(1<<7);
        }

        return 1; 
}

static int led_release (struct inode *node, struct file *filp)
{
    printk("iounmap(0x%x)\n", gpio_con);
    iounmap(gpio_con);
    return 0;
}


static struct file_operations myled_oprs = {
    .owner = THIS_MODULE,
    .open  = led_open,
    .write = led_write,
    .release = led_release,
};
static int myled_init(void)
{
   major = register_chrdev(0, "myled", &myled_oprs);
   led_class = class_create(THIS_MODULE, "myled");
   device_create(led_class, NULL, MKDEV(major, 0), NULL, "ledzzzzzzzz"); 
   gpio_con = (volatile unsigned long *)ioremap(0x01C20824, 1);   //0x01C20824
   gpio_dat = gpio_con + 4;     //0x01C20834        
   *gpio_con &= ~(7<<28);
   *gpio_con |=  (1<<28);
   *gpio_dat &= ~(1<<7);
   return 0;
}

Makefile代码:


#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
/* ledtest on
 *   * ledtest off
 *     */
int main(int argc, char **argv)
{
    int fd;
    unsigned char val = 1;
    fd = open("/dev/ledzzzzzzzz", O_RDWR);
    if (fd < 0)
    {
        printf("can't open!\n");
    }
    if (argc != 2)
    {
        printf("Usage :\n");
        printf("%s <on|off>\n", argv[0]);
        return 0;
    }

    if (strcmp(argv[1], "on") == 0)
    {
        val  = 1;
    }
    else
    {
        val = 0;
    }
    write(fd, &val, 1);
    return 0;
}

相关文章
|
28天前
|
算法 Linux C++
【Linux系统编程】解析获取和设置文件信息与权限的Linux系统调用
【Linux系统编程】解析获取和设置文件信息与权限的Linux系统调用
29 0
|
28天前
|
算法 Linux C++
【Linux系统编程】深入解析Linux中read函数的错误场景
【Linux系统编程】深入解析Linux中read函数的错误场景
202 0
|
28天前
|
Linux 编译器 程序员
【Linux 调试秘籍】深入探索 C++:运行时获取堆栈信息和源代码行数的终极指南
【Linux 调试秘籍】深入探索 C++:运行时获取堆栈信息和源代码行数的终极指南
67 0
|
28天前
|
存储 算法 Linux
【Linux系统编程】深入理解Linux目录扫描函数:scandir目录函数(按条件扫描目录
【Linux系统编程】深入理解Linux目录扫描函数:scandir目录函数(按条件扫描目录
37 0
|
28天前
|
存储 算法 Linux
【Linux系统编程】Linux 文件系统探究:深入理解 struct dirent、DIR 和 struct stat结构
【Linux系统编程】Linux 文件系统探究:深入理解 struct dirent、DIR 和 struct stat结构
40 0
|
1天前
|
Linux Shell Android开发
自动化脚本之GPIO/LED相关适用于Android/Linux
自动化脚本之GPIO/LED相关适用于Android/Linux
8 0
|
14天前
|
关系型数据库 Linux PHP
linux 编译安装php7.2 实测!!
linux 编译安装php7.2 实测!!
10 0
|
15天前
|
Linux 开发者
Linux文件编程(open read write close函数)
通过这些函数,开发者可以在Linux环境下进行文件的读取、写入和管理。 买CN2云服务器,免备案服务器,高防服务器,就选蓝易云。百度搜索:蓝易云
84 4
|
21天前
|
传感器 Linux API
嵌入式Linux串口编程简介
嵌入式Linux串口编程简介
18 1
|
22天前
|
Linux 测试技术 C语言
【Linux】应用编程之C语言文件操作
【Linux】应用编程之C语言文件操作