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

2019-02-15  本文已影响0人  sinlinx123

开发平台

*  芯灵思SinlinxA33开发板
image

实验原理

image

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

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

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

总体代码框架

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;
}


上一篇 下一篇

猜你喜欢

热点阅读