zoukankan      html  css  js  c++  java
  • pcDuino的linux移植五GPIO驱动开发

    调试完pcDuino的led裸板程序,再调pcDuino基于linux内核的gpio驱动开发,以前的问题迎刃而解。本文是在pcDuino的linux移植四简单驱动开发的基础上,做GPIO驱动开发。然后写一个应用测试程序,通过敲命令控制pcduino的TX led亮、灭。同时如果你GPIO4、GPIO5接个LED,也会跟着亮、灭。

    开发环境:
    系统:ubuntu 10.04.4
    单板:pcDuino
    编译器:arm-2009q3-67-arm-none-linux-gnueabi-i686-pc-linux-gnu.tar.bz2

    目标:敲命令控制pcDuino上的TX_LED亮、灭

    一、硬件介绍
    仔细看pcDuino上的原理图和pcDuino的手册,发现二者不是完全对应的,还是以原理图为准。根据原理图知道TX_LED是接到PH15上,可以当做普通IO口用,不需要连跳线

    二、编写GPIO驱动代码
    主要包括2部分,驱动代码first_drv.c和应用测试程序firstdrvtest.c以及Makefile。
    驱动代码first_drv.c

    #include <linux/module.h>
    #include <linux/kernel.h>
    #include <linux/fs.h>
    #include <linux/init.h>
    #include <linux/delay.h>
    #include <asm/uaccess.h>
    #include <asm/irq.h>
    #include <asm/io.h>
    #include <mach/gpio.h>
    #include <mach/hardware.h>
    #include <linux/device.h>
    
    
    static struct class *firstdrv_class;
    static struct class_device *firstdrv_class_dev;
    
    
    volatile unsigned long *gphcfg1;//0x100 ph9 [6:4]001
    volatile unsigned long *gphdat; //0x10c
    static int first_drv_open(struct inode *inode, struct file *file)
    {
    	printk("first_drv_open\n");
    	/* 配置GPh9为输出引脚 gpio4*/
    	*gphcfg1 |= ((0x1<<4)|(0x1<<8)|(0X1<<28));
    	return 0;
    }
    
    
    static ssize_t first_drv_write(struct file *file, const char __user *buf, size_t count,loff_t *ppos)
    {
    	int val;
    	printk("first_drv_write\n");
    	copy_from_user(&val, buf, count); //	copy_to_user();
    
    
    	if (val == 1)
    	{
    		// 点灯
    		*gphdat &= ~((0X1<<9)|(0X1<<10)|(1<<15));
    	}
    	else
    	{
    		// 灭灯
    		*gphdat |= ((0X1<<9)|(0X1<<10)|(1<<15));
    	}
    	
    	return 0;
    }
    
    
    static struct file_operations first_drv_fops ={
    	.owner = THIS_MODULE,
    	.open  = first_drv_open,
    	.write = first_drv_write,
    };
    
    
    int major;
    static int first_drv_init(void)
    {
    	major = register_chrdev(0, "first_drv", &first_drv_fops);
    	firstdrv_class = class_create(THIS_MODULE, "firstdrv");
    	firstdrv_class_dev = device_create(firstdrv_class,NULL,MKDEV(major, 0), NULL, "xyz");
    	gphcfg1 = (volatile unsigned long *)ioremap(0x01c20900, 16);
    	gphdat = (volatile unsigned long *)ioremap(0x01c2090c, 16);//gphcfg1 + 3;
    	return 0;
    }
    
    
    static void first_drv_exit(void)
    {
    	unregister_chrdev(major,"first_drv");
    	device_unregister(firstdrv_class_dev);
    	class_destroy(firstdrv_class);
    	iounmap(gphcfg1);
    	iounmap(gphdat);
    }
    
    
    module_init(first_drv_init);
    module_exit(first_drv_exit);
    
    
    MODULE_LICENSE("GPL");

    文件Makefile:

    KERN_DIR = /home/change/Si/A10/pcduino/linux-sunxi-sunxi-3.0
    
    
    all:
    	make -C $(KERN_DIR) M=`pwd` modules
    	
    clean:
    	make -C $(KERN_DIR) M=`pwd`  modules clean
    	rm -rf modules.order
    
    
    obj-m	+= first_drv.o

    应用测试程序firstdrvtest.c:

    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <stdio.h>
    
    
    /* firstdrvtest on
      * firstdrvtest off
      */
    int main(int argc, char **argv)
    {
    	int fd;
    	int val = 1;
    	fd = open("/dev/xyz", 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, 4);
    	return 0;
    }
    


    三、编译测试

    1.编译驱动first_drv.c
    change@change:~/Si/A10/2_led$  cd ../pcduino/linux-sunxi-sunxi-3.0/drivers/mydrv/led_drv/
    change@change:~/Si/A10/pcduino/linux-sunxi-sunxi-3.0/drivers/mydrv/led_drv$  ls
    first_drv.c   first_drv.mod.c  first_drv.o   firstdrvtest.c  modules.order
    first_drv.ko  first_drv.mod.o  firstdrvtest  Makefile        Module.symvers
    change@change:~/Si/A10/pcduino/linux-sunxi-sunxi-3.0/drivers/mydrv/led_drv$  make clean
    make -C /home/change/Si/A10/pcduino/linux-sunxi-sunxi-3.0 M=`pwd`  modules clean
    make[1]: Entering directory `/home/change/Si/A10/pcduino/linux-sunxi-sunxi-3.0'
      LD      /home/change/Si/A10/pcduino/linux-sunxi-sunxi-3.0/drivers/mydrv/led_drv/built-in.o
      CC [M]  /home/change/Si/A10/pcduino/linux-sunxi-sunxi-3.0/drivers/mydrv/led_drv/first_drv.o
    /home/change/Si/A10/pcduino/linux-sunxi-sunxi-3.0/drivers/mydrv/led_drv/first_drv.c: In function 'first_drv_write':
    /home/change/Si/A10/pcduino/linux-sunxi-sunxi-3.0/drivers/mydrv/led_drv/first_drv.c:30: warning: ignoring return value of 'copy_from_user', declared with attribute warn_unused_result
    /home/change/Si/A10/pcduino/linux-sunxi-sunxi-3.0/drivers/mydrv/led_drv/first_drv.c: In function 'first_drv_init':
    /home/change/Si/A10/pcduino/linux-sunxi-sunxi-3.0/drivers/mydrv/led_drv/first_drv.c:57: warning: assignment from incompatible pointer type
    /home/change/Si/A10/pcduino/linux-sunxi-sunxi-3.0/drivers/mydrv/led_drv/first_drv.c: In function 'first_drv_exit':
    /home/change/Si/A10/pcduino/linux-sunxi-sunxi-3.0/drivers/mydrv/led_drv/first_drv.c:66: warning: passing argument 1 of 'device_unregister' from incompatible pointer type
    include/linux/device.h:692: note: expected 'struct device *' but argument is of type 'struct class_device *'
      Building modules, stage 2.
      MODPOST 1 modules
      CC      /home/change/Si/A10/pcduino/linux-sunxi-sunxi-3.0/drivers/mydrv/led_drv/first_drv.mod.o
      LD [M]  /home/change/Si/A10/pcduino/linux-sunxi-sunxi-3.0/drivers/mydrv/led_drv/first_drv.ko
      CLEAN   /home/change/Si/A10/pcduino/linux-sunxi-sunxi-3.0/drivers/mydrv/led_drv/.tmp_versions
      CLEAN   /home/change/Si/A10/pcduino/linux-sunxi-sunxi-3.0/drivers/mydrv/led_drv/Module.symvers
    make[1]: Leaving directory `/home/change/Si/A10/pcduino/linux-sunxi-sunxi-3.0'
    rm -rf modules.order
    change@change:~/Si/A10/pcduino/linux-sunxi-sunxi-3.0/drivers/mydrv/led_drv$  make
    make -C /home/change/Si/A10/pcduino/linux-sunxi-sunxi-3.0 M=`pwd` modules
    make[1]: Entering directory `/home/change/Si/A10/pcduino/linux-sunxi-sunxi-3.0'
      CC [M]  /home/change/Si/A10/pcduino/linux-sunxi-sunxi-3.0/drivers/mydrv/led_drv/first_drv.o
    /home/change/Si/A10/pcduino/linux-sunxi-sunxi-3.0/drivers/mydrv/led_drv/first_drv.c: In function 'first_drv_write':
    /home/change/Si/A10/pcduino/linux-sunxi-sunxi-3.0/drivers/mydrv/led_drv/first_drv.c:30: warning: ignoring return value of 'copy_from_user', declared with attribute warn_unused_result
    /home/change/Si/A10/pcduino/linux-sunxi-sunxi-3.0/drivers/mydrv/led_drv/first_drv.c: In function 'first_drv_init':
    /home/change/Si/A10/pcduino/linux-sunxi-sunxi-3.0/drivers/mydrv/led_drv/first_drv.c:57: warning: assignment from incompatible pointer type
    /home/change/Si/A10/pcduino/linux-sunxi-sunxi-3.0/drivers/mydrv/led_drv/first_drv.c: In function 'first_drv_exit':
    /home/change/Si/A10/pcduino/linux-sunxi-sunxi-3.0/drivers/mydrv/led_drv/first_drv.c:66: warning: passing argument 1 of 'device_unregister' from incompatible pointer type
    include/linux/device.h:692: note: expected 'struct device *' but argument is of type 'struct class_device *'
      Building modules, stage 2.
      MODPOST 1 modules
      CC      /home/change/Si/A10/pcduino/linux-sunxi-sunxi-3.0/drivers/mydrv/led_drv/first_drv.mod.o
      LD [M]  /home/change/Si/A10/pcduino/linux-sunxi-sunxi-3.0/drivers/mydrv/led_drv/first_drv.ko
    make[1]: Leaving directory `/home/change/Si/A10/pcduino/linux-sunxi-sunxi-3.0'

    2.编译应用测试程序firstdrvtest.c

    change@change:~/Si/A10/pcduino/linux-sunxi-sunxi-3.0/drivers/mydrv/led_drv$  /home/change/tools/arm-2009q3/bin/arm-none-linux-gnueabi-gcc -o firstdrvtest firstdrvtest.c

    其中/home/change/tools/arm-2009q3/bin/arm-none-linux-gnueabi-gcc是我的交叉编译路径,根据自己情况修改。

    change@change:~/Si/A10/pcduino/linux-sunxi-sunxi-3.0/drivers/mydrv/led_drv$ ls
    first_drv.c   first_drv.mod.c  first_drv.o   firstdrvtest.c  modules.order
    first_drv.ko  first_drv.mod.o  firstdrvtest  Makefile        Module.symvers
    change@change:~/Si/A10/pcduino/linux-sunxi-sunxi-3.0/drivers/mydrv/led_drv$cpfirst_drv.ko firstdrvtest /home/change/work/rootfs_dir/fs_mini/home/linux3.0.62/pcduino/

    change@change:~/Si/A10/pcduino/linux-sunxi-sunxi-3.0/drivers/mydrv/led_drv$
    其中/home/change/work/rootfs_dir/fs_mini是我的NFS共享目录,详细配置见我的ubuntu 开发环境配置。程序比较简单,就不分析了,有问题直接留言吧,开始测试吧。

    3.测试

    启动前面pcDuino的linux移植一、二、三、四搭建的驱动开发平台,上电进入pcDuino启动控制台,串口输出如下
    / # ifconfig eth0 172.16.1.111
    <4>wemac wemac.0: WARNING: no IRQ resource flags set.
    [   18.250000] wemac wemac.0: WARNING: no IRQ resource flags set.
    <6>wemac wemac.0: eth0: link up, 100Mbps, full-duplex, lpa 0x45E1
    [   18.400000] wemac wemac.0: eth0: link up, 100Mbps, full-duplex, lpa 0x45E1
    / # ping 172.16.1<7>eth0: no IPv6 routers present
    [   28.860000] eth0: no IPv6 routers present

    PING 172.16.1 (172.16.0.1): 56 data bytes
    ^C
    --- 172.16.1 ping statistics ---
    4 packets transmitted, 0 packets received, 100% packet loss
    / # ping 172.16.1.137
    PING 172.16.1.137 (172.16.1.137): 56 data bytes
    64 bytes from 172.16.1.137: seq=0 ttl=64 time=10.015 ms
    64 bytes from 172.16.1.137: seq=1 ttl=64 time=1.013 ms
    64 bytes from 172.16.1.137: seq=2 ttl=64 time=1.735 ms
    64 bytes from 172.16.1.137: seq=3 ttl=64 time=0.814 ms
    ^C
    --- 172.16.1.137 ping statistics ---
    4 packets transmitted, 4 packets received, 0% packet loss
    round-trip min/avg/max = 0.814/3.394/10.015 ms
    / # ls
    bin      etc      lib      mnt      run      sys      usr
    dev      home     linuxrc  proc     sbin     tmp      var
    / # mount -t nfs -o nolock 172.16.1.137:/home/change/work/rootfs_dir/fs_mini /mn
    t/
    / # ls /mnt/
    bin      etc      lib      mnt      root     sys      usr
    dev      home     linuxrc  proc     sbin     tmp
    / # cd /mnt/home/linux-3.0.62/pcduino/
    /mnt/home/linux-3.0.62/pcduino # ls
    first_drv.ko  firstdrvtest  gpio_drv.ko   gpiodrvtest
    /mnt/home/linux-3.0.62/pcduino # insmod first_drv.ko 
    /mnt/home/linux-3.0.62/pcduino # lsmod 
    first_drv 1768 0 - Live 0xbf000000
    /mnt/home/linux-3.0.62/pcduino # ./firstdrvtest off
    first_drv_open
    [  303.610000] first_drv_open
    first_drv_write
    [  303.610000] first_drv_write
    /mnt/home/linux-3.0.62/pcduino # ./firstdrvtest on
    first_drv_open
    [  309.510000] first_drv_open
    first_drv_write
    [  309.510000] first_drv_write
    /mnt/home/linux-3.0.62/pcduino #
    可以看到执行./firstdrvtest off ,pcDuino上的TX LED就灭,执行./firstdrvtest on,pcDuino上的TX LED就亮。测试基本正常,卸载刚刚加载的驱动如下;
    /mnt/home/linux-3.0.62/pcduino # rmmod first_drv
    /mnt/home/linux-3.0.62/pcduino # lsmod 
    /mnt/home/linux-3.0.62/pcduino #
    基本OK了,下一步继续完善驱动。






     

  • 相关阅读:
    [转] packagelock.json
    前端框架和技术
    typescript
    微信小程序登陆流程
    Introduction to my galaxy engine 4: Test on local light model
    Introduction to my galaxy engine 3: Local light model
    Introduction to my galaxy engine 5: Differed Lighting
    Introduction to my galaxy engine 2: Depth of field
    自己整理的一些国外免费3D模型网站,以后还会陆续添加
    Introduction to my galaxy engine 6: Differed Lighting 2
  • 原文地址:https://www.cnblogs.com/javawebsoa/p/3098732.html
Copyright © 2011-2022 走看看