一、概述

      GPIO是非常典型的字符型设备,相对比较简单。

      测试环境:TQ2440开发板+Linux2.6.30.4。

二、编写驱动程序实例

1、编写驱动程序

      驱动程序源文件EmbedSky_gpio.c。

#include <linux/miscdevice.h>
#include <linux/delay.h>
#include <asm/irq.h>
#include <mach/regs-gpio.h>
#include <mach/hardware.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/fs.h>
#include <linux/types.h>
#include <linux/delay.h>
#include <linux/moduleparam.h>
#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/ioctl.h>
#include <linux/cdev.h>
#include <linux/string.h>
#include <linux/list.h>
#include <linux/pci.h>
#include <asm/uaccess.h>
#include <asm/atomic.h>
#include <asm/unistd.h>

#define    DEVICE_MAJOR     221
#define    DEVICE_NAME      "GPIO-Control"

/* 应用程序执行ioctl(fd, cmd, arg)时的第2个参数 */
#define IOCTL_GPIO_ON    1
#define IOCTL_GPIO_OFF    0

/* 用来指定LED所用的GPIO引脚 */
static unsigned long gpio_table [] =
{
    S3C2410_GPB5,
    S3C2410_GPB6,
    S3C2410_GPB7,
    S3C2410_GPB8,
};

/* 用来指定GPIO引脚的功能:输出 */
static unsigned int gpio_cfg_table [] =
{
    S3C2410_GPB5_OUTP,
    S3C2410_GPB6_OUTP,
    S3C2410_GPB7_OUTP,
    S3C2410_GPB8_OUTP,
};

/* cmd 1 打开LED |0 关闭LED; arg 操作LED的编号 取值范围1-4 */
static int tq2440_gpio_ioctl( struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { if (arg > 4) { return -EINVAL; } switch(cmd) { case IOCTL_GPIO_ON: // 设置指定引脚的输出电平为0 s3c2410_gpio_setpin(gpio_table[arg], 0); return 0; case IOCTL_GPIO_OFF: // 设置指定引脚的输出电平为1 s3c2410_gpio_setpin(gpio_table[arg], 1); return 0; default: return -EINVAL; } } static struct file_operations dev_fops = { .owner = THIS_MODULE, .ioctl = tq2440_gpio_ioctl, }; static int __init dev_init(void) { int ret; int i; for (i = 0; i < 4; i++) { s3c2410_gpio_cfgpin(gpio_table[i], gpio_cfg_table[i]); s3c2410_gpio_setpin(gpio_table[i], 1); } ret = register_chrdev(DEVICE_MAJOR, DEVICE_NAME, &dev_fops ); if (ret < 0) { printk("<1>"DEVICE_NAME " can't register major number.\n"); return ret; } printk("<1>"DEVICE_NAME " initialized.\n"); return 0; } static void __exit dev_exit(void) { unregister_chrdev(DEVICE_MAJOR, DEVICE_NAME); printk("<1>"DEVICE_NAME " removed.\n"); } module_init(dev_init); module_exit(dev_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("www.embedsky.net"); MODULE_DESCRIPTION("GPIO control for EmbedSky SKY2440/TQ2440 Board");

2、编写Makefile文件

KERN_DIR = /opt/EmbedSky/linux-2.6.30.4

all:
    make -C $(KERN_DIR) M=`pwd` modules 

clean:
    make -C $(KERN_DIR) M=`pwd` modules clean
    rm -rf modules.order

obj-m    += EmbedSky_gpio.o

三、驱动程序测试

1、编译驱动前说明

      驱动文件所在的目录不是Linux内核源码的子目录。

      驱动文件所在目录为“opt/EmbedSky/work/test”。

      Linux内核源码所在目录为“/opt/EmbedSky/linux-2.6.30.4”。

2、在Ubuntu下编译驱动

      注意:在编译驱动之前要先编译Linux内核镜像,否则驱动编译不通过。

#cd /opt/EmbedSky/work/test
#make

      编译成功后,会看到一个ko文件。

3、在Ubuntu下拷贝驱动到开发板

#cd /opt/EmbedSky/root_nfs/lib
#cp /opt/EmbedSky/work/EmbedSky_hello/EmbedSky_gpio.ko ./

       说明:开发板使用nfs根文件系统启动,使用Ubuntu共享的根文件系统所在目录为“/opt/EmbedSky/root_nfs“。

4、在开发板上安装驱动

      开发板Linux系统从nfs根文件系统启动。

#cd /lib
#insmode EmbedSky_hello.ko

      可以观察到开发板4盏LED灯都熄灭了。(因为驱动程序加载的时候,把4盏灯的初始胡状态设置为关闭状态)

5、查看驱动注册信息

image

 四、应用程序测试驱动

1、编写应用程序代码

      ledstest.c内容如下:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>

int main(int argc, char **argv)
{
    int cmd;
    int led_no;
    int fd;

    if (argc != 3)
    {
        fprintf(stderr, "Usage: leds led_no on|off\n");
        exit(1);                
    }

    if (sscanf(argv[1], "%d", &led_no) != 1 || led_no < 1 || led_no > 4) {
        fprintf(stderr, "Usage: leds led_no on|off\n");
        exit(1);
    }
                
    if (!strcmp(argv[2], "on"))
    {
        cmd = 1;
    }
    else if (!strcmp(argv[2], "off"))
    {
        cmd = 0;
    }
    else
    {
        exit(1);                
    }

    fd = open("/dev/leds", 0);
    
    if (fd < 0) {
        fprintf(stderr, "can't open!\n");
        exit(1);
    }
                
    ioctl(fd, cmd, (led_no-1));
    close(fd);
    return 0;
}

2、在Ubuntu上编译应用程序

#arm-linux-gcc ledstest.c -o ledstest

      通过这条命令,就能编译出一个上层应用ledstest。

3、在Ubuntu下拷贝上层应用测试程序到开发板

#cd /opt/EmbedSky/root_nfs/usr/bin
#cp /opt/EmbedSky/work/test/ledstest ./

4、在开发板Linux系统上创建设备节点

#mknod /dev/hellodev c 231 0

5、执行测试代码

#cd /usr/bin
#./ledstest

      测试结果:

image

 

参考资料:《嵌入式Linux应用开发完全手册》

posted on 2026-01-07 23:13  amanlikethis  阅读(7)  评论(0)    收藏  举报