分享

LED驱动(轮询方式)在FL2440的开发(2.6.33.7内核)

 lchjczw 2012-04-10
一、开发环境
    主   机:fedora 14 (2.6.33.7)
    开发板:FL2440(nandflash:K9F1G08 128m)
    编译器:arm-linux-gcc 4.3.2
 
二、原理分析
    1.  硬件原理图分析。由原理图得知LED电路是共阳极的,LED0、LED1、LED2、LED3分别由2440的GPB5、GPB6、GPB8、GPB10口控制的,当GPB5、GPB6、GPB8、GPB10输出低电平时,相应的LED便发亮,反之,LED则熄灭。
 
三、实现步骤
    1. 去掉内核已有的LED驱动设置,因为IO口与mini2440开发板的不一致,根本就不能控制板上的LED。
  1. #gedit arch/arm/plat-s3c24xx/common-smdk.c
  1. /* LED devices */
  2. /*
  3. static struct s3c24xx_led_platdata smdk_pdata_led4 = {
  4.     .gpio = S3C2410_GPF4,
  5.     .flags = S3C24XX_LEDF_ACTLOW | S3C24XX_LEDF_TRISTATE,
  6.     .name = "led4",
  7.     .def_trigger = "timer",
  8. };

  9. static struct s3c24xx_led_platdata smdk_pdata_led5 = {
  10.     .gpio = S3C2410_GPF5,
  11.     .flags = S3C24XX_LEDF_ACTLOW | S3C24XX_LEDF_TRISTATE,
  12.     .name = "led5",
  13.     .def_trigger = "nand-disk",
  14. };

  15. static struct s3c24xx_led_platdata smdk_pdata_led6 = {
  16.     .gpio = S3C2410_GPF6,
  17.     .flags = S3C24XX_LEDF_ACTLOW | S3C24XX_LEDF_TRISTATE,
  18.     .name = "led6",
  19. };

  20. static struct s3c24xx_led_platdata smdk_pdata_led7 = {
  21.     .gpio = S3C2410_GPF7,
  22.     .flags = S3C24XX_LEDF_ACTLOW | S3C24XX_LEDF_TRISTATE,
  23.     .name = "led7",
  24. };

  25. static struct platform_device smdk_led4 = {
  26.     .name = "s3c24xx_led",
  27.     .id = 0,
  28.     .dev = {
  29.         .platform_data = &smdk_pdata_led4,
  30.     },
  31. };

  32. static struct platform_device smdk_led5 = {
  33.     .name = "s3c24xx_led",
  34.     .id = 1,
  35.     .dev = {
  36.         .platform_data = &smdk_pdata_led5,
  37.     },
  38. };

  39. static struct platform_device smdk_led6 = {
  40.     .name = "s3c24xx_led",
  41.     .id = 2,
  42.     .dev = {
  43.         .platform_data = &smdk_pdata_led6,
  44.     },
  45. };

  46. static struct platform_device smdk_led7 = {
  47.     .name = "s3c24xx_led",
  48.     .id = 3,
  49.     .dev = {
  50.         .platform_data = &smdk_pdata_led7,
  51.     },
  52. };*/
  1. static struct platform_device __initdata *smdk_devs[] = {
  2.     &s3c_device_nand,
  3.     /*&smdk_led4,
  4.     &smdk_led5,
  5.     &smdk_led6,
  6.     &smdk_led7,*/
  7. };
  1. void __init smdk_machine_init(void)
  2. {
  3.     /* Configure the LEDs (even if we have no LED support)*/
  4.     /*
  5.     s3c2410_gpio_cfgpin(S3C2410_GPF4, S3C2410_GPF4_OUTP);
  6.     s3c2410_gpio_cfgpin(S3C2410_GPF5, S3C2410_GPF5_OUTP);
  7.     s3c2410_gpio_cfgpin(S3C2410_GPF6, S3C2410_GPF6_OUTP);
  8.     s3c2410_gpio_cfgpin(S3C2410_GPF7, S3C2410_GPF7_OUTP);

  9.     s3c2410_gpio_setpin(S3C2410_GPF4, 1);
  10.     s3c2410_gpio_setpin(S3C2410_GPF5, 1);
  11.     s3c2410_gpio_setpin(S3C2410_GPF6, 1);
  12.     s3c2410_gpio_setpin(S3C2410_GPF7, 1);*/

  13.     if (machine_is_smdk2443())
  14.         smdk_nand_info.twrph0 = 50;

  15.     s3c_device_nand.dev.platform_data = &smdk_nand_info;

  16.     platform_add_devices(smdk_devs, ARRAY_SIZE(smdk_devs));

  17.     s3c_pm_init();
  18. }

    2. 编写适合fl2440开发板的LED驱动,代码如下,文件名称:fl2440_leds.c

  1. /*
  2.  *==============================================
  3.  *Name : fl2440_leds.c
  4.  *Author : y.q.yang
  5.  *Date : 17/2/2011
  6.  *Copyright : GPL
  7.  *Description : fl2440 leds driver
  8.  *==============================================
  9.  */

  10. #include <linux/kernel.h>
  11. #include <linux/module.h>
  12. #include <linux/init.h>
  13. #include <linux/errno.h>
  14. #include <linux/fs.h>
  15. //#include <linux/sched.h>
  16. //#include <linux/poll.h>    //poll要用到的头文件

  17. #include <mach/hardware.h>
  18. #include <mach/regs-gpio.h>
  19. #include <mach/gpio-fns.h>
  20. #include <mach/gpio-nrs.h>

  21. #define DEVICER_NAME    "fl2440_leds"
  22. #define DEVICER_MAJOR    231
  23. #define LED_ON            0
  24. #define LED_OFF            1
  25. #define LED_COUNT        4

  26. #define S3C2410_GPIONO(bank,offset) ((bank) + (offset))
  27. #define S3C2410_GPIO_BANKB (32*1)
  28. #define S3C2410_GPB5 S3C2410_GPIONO(S3C2410_GPIO_BANKB, 5)
  29. #define S3C2410_GPB6 S3C2410_GPIONO(S3C2410_GPIO_BANKB, 6)
  30. #define S3C2410_GPB8 S3C2410_GPIONO(S3C2410_GPIO_BANKB, 8)
  31. #define S3C2410_GPB10 S3C2410_GPIONO(S3C2410_GPIO_BANKB, 10)

  32. #define S3C2410_GPB5_OUTP    (0x01 << 10)
  33. #define S3C2410_GPB6_OUTP    (0x01 << 12)
  34. #define S3C2410_GPB8_OUTP    (0x01 << 16)
  35. #define S3C2410_GPB10_OUTP    (0x01 << 20)


  36. //硬件设备资源结构体
  37. struct led_desc
  38. {
  39.     int pin;            //对应的IO引脚
  40.     int pin_setting;    //引脚配置
  41. };

  42. static struct led_desc led_configs[] =
  43. {
  44.     {S3C2410_GPB5,S3C2410_GPB5_OUTP},
  45.     {S3C2410_GPB6,S3C2410_GPB6_OUTP},
  46.     {S3C2410_GPB8,S3C2410_GPB8_OUTP},
  47.     {S3C2410_GPB10,S3C2410_GPB10_OUTP},
  48. };

  49. static int leds_open(struct inode *inode, struct file *filp)
  50. {
  51.     return 0;
  52. }

  53. static int leds_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
  54. {
  55.     if(arg<0 || arg>3)
  56.     {
  57.         return -EINVAL;
  58.     }
  59.     
  60.     switch(cmd)
  61.     {
  62.         case LED_ON:
  63.             s3c2410_gpio_setpin(led_configs[arg].pin,~(LED_ON));
  64.             break;
  65.             
  66.         case LED_OFF:
  67.             s3c2410_gpio_setpin(led_configs[arg].pin,~(LED_OFF));
  68.             break;
  69.             
  70.         default:
  71.             return -EINVAL;
  72.     }
  73.     return 0;
  74. }

  75. struct file_operations leds_fops =
  76. {
  77.     .owner = THIS_MODULE,
  78.     .open = leds_open,
  79.     .ioctl = leds_ioctl,
  80. };

  81. static int __init led_init(void)
  82. {
  83.     int i,ret;
  84.     
  85.     for(i=0; i<LED_COUNT; i++)
  86.     {
  87.         s3c2410_gpio_cfgpin(led_configs[i].pin, led_configs[i].pin_setting);
  88.         s3c2410_gpio_setpin(led_configs[i].pin,~(LED_OFF));
  89.     }
  90.     
  91.     ret = register_chrdev(DEVICER_MAJOR, DEVICER_NAME, &leds_fops);
  92.     
  93.     if(ret < 0)
  94.     {
  95.         printk(DEVICER_NAME "register failed\n");
  96.         return ret;
  97.     }
  98.     
  99.     return ret;
  100. }

  101. static void __exit led_exit(void)
  102. {
  103.     unregister_chrdev(DEVICER_MAJOR, DEVICER_NAME);
  104. }

  105. module_init(led_init);
  106. module_exit(led_exit);

  107. MODULE_LICENSE("GPL");
  108. MODULE_AUTHOR("y.q.yang");
  109. MODULE_DESCRIPTION("FL2440 led driver");

    3. 把LED驱动代码部署到内核中去

  1. #cp -f fl2440_leds.c /linux-2.6.33.7/drivers/char //把驱动源码复制到内核驱动的字符设备下
  2. #vim /linux-2.6.33.7/drivers/char/Kconfig //添加LED设备配置
  3. config FL2440_LEDS
  4.     tristate "FL2440 Leds Device"
  5.     depends on ARCH_S3C2440
  6.     default y
  7.     ---help---
  8.       FL2440 User Leds

  9. #gedit /linux-2.6.33.7/drivers/char/Makefile //添加LED设备配置
  10. obj-$(CONFIG_FL2440_LEDS) += fl2440_leds.o

    4. 配置内核,选择LED设备选项

  1. #make menuconfig
  2. Device Drivers --->
  3.     Character devices --->
  4.         <*> FL2440 Leds Device (NEW)

    5. 编译内核并下载到开发板上,查看已加载的设备:#cat /proc/devices,可以看到fl2440_leds的主设备号为231

  1. [root@yyq2440 /]# cat /proc/devices
  1. 90 mtd
  2.  99 ppdev
  3. 116 alsa
  4. 128 ptm
  5. 136 pts
  6. 180 usb
  7. 188 ttyUSB
  8. 189 usb_device
  9. 204 s3c2410_serial
  10. 231 fl2440_leds
  11. 232 fl2440_buttons
  12. 254 rtc

  13. Block devices:
  14.   1 ramdisk
  15. 259 blkext

四、测试驱动

    1. 编写应用程序测试LED驱动,文件名:leds_test.c

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <fcntl.h>
  4. #include <sys/ioctl.h>

  5. int main(int argc, char **argv)
  6. {
  7.     int turn, index, fd;

  8.     //检测输入的参数合法性
  9.     if(argc != 3 || sscanf(argv[2], "%d", &index) != 1 || index < 1 || index > 4)
  10.     {
  11.         printf("Usage: leds_test on|off 1|2|3|4\n");
  12.         exit(1);
  13.     }

  14.     if(strcmp(argv[1], "on") == 0)
  15.     {
  16.         turn = 1;
  17.     }
  18.     else if(strcmp(argv[1], "off") == 0)
  19.     {
  20.         turn = 0;
  21.     }
  22.     else
  23.     {
  24.         printf("Usage: leds_test on|off 1|2|3|4\n");
  25.         exit(1);
  26.     }

  27.     //打开LED设备
  28.     fd = open("/dev/fl2440_leds", 0);

  29.     if(fd < 0)
  30.     {
  31.         printf("Open Led Device Faild!\n");
  32.         exit(1);
  33.     }

  34.     //IO控制
  35.     ioctl(fd, turn, index - 1);

  36.     //关闭LED设备
  37.     close(fd);

  38.     return 0;
  39. }

    2. 在开发主机上交叉编译测试应用程序,并复制到文件系统的/usr/sbin目录下,然后重新编译文件系统下载到开发板上

  1. #arm-linux-gcc -o leds_test leds_test.c

    3. 在开发板上的文件系统中创建一个LED设备的节点,然后运行测试程序,效果图如下,观测开发板上的LED灯,可以看到每一步的操作对应的LED会点亮或者熄灭

  1. [root@yyq2440 /]# mknod /dev/fl2440_leds c 231 0
  2. [root@yyq2440 /]# leds_test --help
  3. Usage: leds_test on|off 1|2|3|4

  4. [root@yyq2440 /]# leds_test on 1
  5. [root@yyq2440 /]# leds_test on 2
  6. [root@yyq2440 /]# leds_test on 3
  7. [root@yyq2440 /]# leds_test on 4
  8. [root@yyq2440 /]# leds_test on 4
  9. [root@yyq2440 /]# leds_test on 3
  10. [root@yyq2440 /]# leds_test on 2
  11. [root@yyq2440 /]# leds_test on 1

五、存在问题。

    当执行#leds_test off *(*表示LED的序号1~4)的时候,序号比*大的Led也会一起灭掉。原因暂时还没找到。

 

2011-02-17

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多