天嵌 ARM开发社区

 找回密码
 注册
查看: 2902|回复: 2

TQ210 LED驱动+流水灯(转)

[复制链接]
非也 发表于 2015-4-20 15:45:25 | 显示全部楼层 |阅读模式
本帖最后由 非也 于 2015-4-21 09:45 编辑

TQ210 LED驱动及测试
1.      编写led驱动
1.1 在系统中创建目录/home/share/led/
  1. #mkdir –p /home/share/led
复制代码


进入led目录
  1. #cd /home/share/led
复制代码


1.2创建源码文件led_driver.c
  1. #vim led_driver.c
复制代码


源码内容见附件一。
保存退出.
1.3创建并编辑Makefile
在该目录下创建Makefile文件,将驱动程序编译成模块。
#vim Makefile
内容如下:
  1. oj-m +=led_driver.o
  2. CURRENT_PATH := /home/share/led
  3. LINUX_KERNEL ?= /home/share/learning/linux-2.6.35
  4. #LINUX_KERNEL_PATH := $(LINUX_KERNEL)
  5. default:
  6.          $(MAKE) -C $(LINUX_KERNEL) m=$(CURRENT_PATH) modules
  7. clean:
  8.          $(MAKE) -C $(LINUX_KERNEL) M=$(CURRENT_PATH) clean
复制代码


2.      编译
TQ210使用天嵌提供交叉编译器,路径:/home/share/tmp/opt/EmbedSky/4.4.6/bin
在该目录下直接make即可
#make
3. 测试led驱动
测试代码:见附件二
使用交叉编译工具编译程序:
  1. # arm-linux-gcc -o led_test led_test.c
复制代码


将生成的可执行程序led_test复制到nfs文件系统/home/share/nfsboot/rootfs中/mnt目录下;
在超级终端上控制开发板。
挂载好nfs文件系统:
  1. #mount –t nfs 10.10.84.41:/home/share/nfsboot/rootfs –o nolock /mnt
复制代码


进入挂载在/mnt 目录下的nfs文件系统内并且进入内部/mnt目录下:
#cd /mnt   //此目录是开发版的子目录
#cd /mnt   //此目录是挂载的宿主机上的nfs文件系统的子目录
执行可执行文件:
  1. # ./led_test
复制代码


出现段错误提示,原因参数不正确,还需要输入led的序号,以及开关指令。测试程序没有做好参数检查,所以会段错误在代码中对argc进行判断即可。
#./led_test   2       on     //打开第二个led
#./led_test      2       off       //关掉第二个led
开发板上两个LED灯均能正确控制,至此led驱动及测试代码试验完成。
附件一led驱动源码
/***********************************************************************************
* drivers/char/tq210_leds.c
* 功能简要:
*       该驱动注册一个字符设备“/dev/led”, 用于2个LED。
* 函数简介:
*       static void tq210_debug_leds(unsigned int cmd,unsigned long arg),用于内核驱动调试
* 提供的外部接口:
*       ioctol(struct inode *inode,struct file *file,unsigned int brightness);
*       用于LED的亮,灭。
* 调用实例:
*       提供控制台,命令式的测试程序。
*
*************************************************************************************/
  1. #include <linux/miscdevice.h>
  2. #include <linux/input.h>
  3. #include <linux/clk.h>
  4. #include <linux/delay.h>
  5. #include <asm/io.h>
  6. #include <asm/uaccess.h>
  7. #include <mach/map.h>
  8. #include <mach/gpio.h>
  9. //#include <mach/gpio-bank.h>
  10. #include <mach/regs-gpio.h>
  11. #include <plat/gpio-core.h>
  12. #include <plat/gpio-cfg.h>
  13. #include <plat/gpio-cfg-helpers.h>
  14. #define DEVICE_NAME "led"
  15. /* 应用程序执行ioctl(fd, cmd, arg)时的第2个参数 */
  16. /*the second parameter that application program execute*/
  17. #define IOCTL_GPIO_ON         1
  18. #define IOCTL_GPIO_OFF        0
  19. /* 用来指定LED所用的GPIO引脚 */
  20. /*appoint the pin the LED will use*/
  21. static unsigned long gpio_table [] =
  22. {
  23.          S5PV210_GPC0(3),
  24.          S5PV210_GPC0(4),
  25. };
  26. /* 用来指定GPIO引脚的功能:输出 */
  27. /*appoint the function of the pin:out put*/
  28. static unsigned int gpio_cfg_table [] =
  29. {
  30.          S3C_GPIO_SFN(1),
  31.          S3C_GPIO_SFN(1),
  32. };
  33. //static char gpio_name[][]={{"GPC0_3"},{"GPC0_4"}};
  34. #ifdef CONFIG_TQ210_DEBUG_LEDS
  35. static void tq210_debug_leds(unsigned int cmd,unsigned long arg)
  36. {
  37.          gpio_direction_output(gpio_table[arg], cmd);
  38.          //s3c_gpio_setpin(gpio_table[arg], cmd);
  39. }
  40. static void toggle_led(unsigned int cmd,unsigned long arg)
  41. {
  42.          int loop=0;
  43.          printk("%s : led %ld toggle now: \n",__func__,arg);
  44.          for(;loop<11;loop++)
  45.          {        cmd = loop%2;
  46.                   printk("leds %d %s \n",arg+1,(cmd)?"on":"o   ff");
  47.                    tq210_debug_leds(cmd,arg);
  48.                    mdelay(1000);
  49.          }
  50. }
  51. #endif
  52. /**
  53. *函数功能:打开/dev/led设备,设备名是:/dev/led
  54. *fuction:open /dev/led device ,devce name: /dev/led
  55. **/
  56. static int tq210_gpio_open(struct inode *inode, struct file *file)
  57. {
  58.          int i;
  59.          int err;
  60.          err = gpio_request(gpio_table[0], "GPC0_3");
  61.          if(err)
  62.          {
  63.                    printk(KERN_ERR "failed to request GPC0_3 for LVDS PWDN pin\n");
  64.         return err;
  65.          }
  66.          err = gpio_request(gpio_table[1], "GPC0_4");
  67.          if(err)
  68.          {
  69.                    printk(KERN_ERR "failed to request GPC0_4 for LVDS PWDN pin\n");
  70.         return err;
  71.          }
  72.          printk(KERN_INFO " leds opened\n");
  73.          for (i = 0; i < sizeof(gpio_table)/sizeof(unsigned long); i++)
  74.          {
  75.                    s3c_gpio_cfgpin(gpio_table, gpio_cfg_table);
  76.                    gpio_direction_output(gpio_table, 0);
  77.                    //s3c_gpio_setpin(gpio_table, 0);
  78.          }
  79. #ifdef CONFIG_TQ210_DEBUG_LEDS
  80.          for (i = 0; i < sizeof(gpio_table)/sizeof(unsigned long); i++)
  81.          {
  82.                    toggle_led(1,i);
  83.          }
  84. #endif
  85.          return 0;
  86. }
  87. /**
  88. *函数功能:用于控制led的亮灭
  89. *fuction:control the led /turn on & turn off
  90. *控制字为cmd,arg为控制哪个灯的亮灭取值范围为0-1:cmd为IOCTL_GPIO_ON时亮,cmd为IOCTL_GPIO_OFF为灭
  91. *control byte is cmd; arg appointed which led wile be turn on or off,it can be 0 and 1;IOCTL_GPIO_ON:turn on,IOCTL_GPIO_OFF:turn off.
  92. **/
  93. static long tq210_gpio_ioctl(
  94.          struct inode *inode,
  95.          struct file *file,
  96.          unsigned int cmd,
  97.          unsigned long arg)
  98. {
  99.          arg -= 1;
  100.          if (arg > sizeof(gpio_table)/sizeof(unsigned long))
  101.          {
  102.                    return -EINVAL;
  103.          }
  104.          switch(cmd)
  105.          {
  106.                    case IOCTL_GPIO_ON:
  107.                             // 设置指定引脚的输出电平为1
  108.                             gpio_direction_output(gpio_table[arg], 1);
  109.                             //s3c_gpio_setpin(gpio_table[arg], 1);
  110.                             return 0;
  111.                    case IOCTL_GPIO_OFF:
  112.                             // 设置指定引脚的输出电平为0
  113.                             gpio_direction_output(gpio_table[arg], 0);
  114.                             //s3c_gpio_setpin(gpio_table[arg], 0);
  115.                             return 0;
  116.                    default:
  117.                             return -EINVAL;
  118.          }
  119. }
  120. static int tq210_gpio_close(struct inode *inode, struct file *file)
  121. {
  122.          gpio_free(gpio_table[0]);
  123.          gpio_free(gpio_table[1]);
  124.          printk(KERN_INFO "TQ210 LEDs driver successfully close\n");
  125.          return 0;
  126. }
  127. /*驱动接口设置*/
  128. /*setting the interface of the driver*/
  129. static struct file_operations dev_fops = {
  130.          .owner     =       THIS_MODULE,
  131.          .ioctl         =       tq210_gpio_ioctl,
  132.          .open =   tq210_gpio_open,
  133.          .release =        tq210_gpio_close,
  134. };
  135. /*设备结构的设置*/
  136. /*setting the architecture of the device*/
  137. static struct miscdevice misc = {
  138.          .minor = MISC_DYNAMIC_MINOR,
  139.          .name = DEVICE_NAME,
  140.          .fops = &dev_fops,
  141. };
  142. /*初始化设备,配置对应的IO,以及注册设备*/
  143. /*init the device, config the right IO and register the device*/
  144. static int __init dev_init(void)
  145. {
  146.          int ret;
  147.          int i;
  148.          int err;
  149.          #ifdef CONFIG_TQ210_DEBUG_LEDS
  150.          err = gpio_request(gpio_table[0], "GPC0_3");
  151.          if(err)
  152.          {
  153.                    printk(KERN_ERR "failed to request GPC0_3 for LVDS PWDN pin\n");
  154.         return err;
  155.          }
  156.          err = gpio_request(gpio_table[1], "GPC0_4");
  157.          if(err)
  158.          {
  159.                    printk(KERN_ERR "failed to request GPC0_4 for LVDS PWDN pin\n");
  160.         return err;
  161.          }
  162.          for (i = 0; i < sizeof(gpio_table)/sizeof(unsigned long); i++)
  163.          {
  164.                    //gpio_request(gpio_table[0],gpio_name);
  165.                    s3c_gpio_cfgpin(gpio_table, gpio_cfg_table);//配置管脚为输出config the pin to out put
  166.                    gpio_direction_output(gpio_table, 0);
  167.                    //s3c_gpio_setpin(gpio_table, 0);//设置管脚为低电平config the pin to low level
  168.                    s3c_gpio_setpull(gpio_table, S3C_GPIO_PULL_NONE);
  169.          }
  170.          #endif
  171.          ret = misc_register(&misc);
  172.          printk(KERN_INFO "TQ210 LEDs driver successfully probed\n");
  173.          #ifdef CONFIG_TQ210_DEBUG_LEDS
  174.          for (i = 0; i < sizeof(gpio_table)/sizeof(unsigned long); i++)
  175.          {
  176.                    toggle_led(1,i);
  177.          }
  178.          #endif
  179.          return ret;
  180. }
  181. /*注销设备*/
  182. /*log out the device*/
  183. static void __exit dev_exit(void)
  184. {
  185.          misc_deregister(&misc);
  186.          gpio_free(gpio_table[0]);
  187.          gpio_free(gpio_table[1]);
  188.          printk(KERN_INFO "TQ210 LEDs driver successfully exit\n");
  189. }
  190. module_init(dev_init);
  191. module_exit(dev_exit);
  192. MODULE_LICENSE("GPL");
  193. MODULE_AUTHOR("www.embedsky.com");
  194. MODULE_DESCRIPTION("LEDS' Driver");
  195. 附件二 led测试源码
  196. /*FILENAME:led_test.c
  197. *AUTHOR:Michael Li
  198. *DATE:2013-06-03
  199. *DESCRIPTION:the test of the led driver
  200. * */
  201. #include<stdio.h>
  202. #include<fcntl.h>
  203. #define DEVICENAME "/dev/led"
  204. #define IOCTL_LED_ON 1
  205. #define IOCTL_LED_OFF 0
  206. int main(int argc, char **argv)
  207. {
  208.     FILE *fd;
  209.     int led_no = 0;
  210.     fd = (FILE *)open(DEVICENAME,0);
  211.          if(argc < 3)
  212.          {
  213.                    printf("The arguments you input are wrong\n");
  214.                    printf("USE:\n");
  215.                    printf("\t\t./program\tled-number\ton/off\n");
  216.                    return -1;
  217.          }
  218.     //led_no = strtoul(argv[1],0,0) -1;//its wrong to set like this
  219.          led_no = strtoul(argv[1],0,0);//operate the led_1 by input 1 and led_2 by input 2
  220.     printf("111111\n");
  221.     if(!strcmp(argv[2],"on"))//turn on the led
  222.     {
  223.         ioctl(fd,IOCTL_LED_ON,led_no);
  224.                    printf("you want the %d on\n",led_no);
  225.     }
  226.     else if(!strcmp(argv[2],"off"))//turn off the led
  227.     {
  228.         ioctl(fd,IOCTL_LED_OFF,led_no);   
  229.     }
  230.     else printf("error!\n");
  231.     return 0;
  232. }
  233. 附件三:流水灯
  234. /*FILENAME:led_test.c
  235. *AUTHOR:Michael Li
  236. *DATE:2013-06-03
  237. *DESCRIPTION:the test of the led driver,please refer to the label "usage:" below.
  238. * */
  239. #include<stdio.h>
  240. #include<fcntl.h>
  241. #include <signal.h>
  242. //#include <time.h>
  243. #include <sys/time.h>
  244. #define DEVICENAME "/dev/led"
  245. #define IOCTL_LED_ON 1
  246. #define IOCTL_LED_OFF 0
  247. void sigoutime();
  248. void timer_init();
  249. void delay(int time);
  250. int time_1= 0;
  251. int main(int argc, char **argv)
  252. {
  253.     FILE *fd;
  254.     int led_no = 0;
  255.          int i = 0;
  256.     fd = (FILE *)open(DEVICENAME,0);
  257.     int delay_grade = 0;
  258.          timer_init();
  259. usage:     
  260.          if(argc < 3)
  261.          {
  262.                    printf("The arguments you input are wrong\n");
  263.                    printf("USE:\n");
  264.                    printf("\t./program\t<right/left/both>\t<1/2/3>\n");
  265.                    printf("\t3:slow;2:faster;1:fastest\n");
  266.                    printf("\teg: ./led_flow\tleft\t1\n\tlet the led light start from left and the speed is the fastest\n");
  267.                    return -1;
  268.          }
  269.         
  270.          if(!strcmp(argv[2],"1"))
  271.          delay_grade = 1;//20ms
  272.          else if (!(argv[2],"2"))
  273.          delay_grade = 15;//300ms
  274.          else if(!(argv[2],"3"))
  275.          delay_grade = 50;//1s
  276.          else
  277.                    delay_grade = 30;//600ms
  278.                   
  279.     if(!strcmp(argv[1],"left"))//turn on the led
  280.     {
  281.         for(i=0;i<40;i++)
  282.                    {
  283.                             if((i%2)!=0)
  284.                             {
  285.                                      led_no = 1;
  286.                             }
  287.                             else
  288.                                      led_no = 2;
  289.                             ioctl(fd,IOCTL_LED_ON,led_no);
  290.                             printf("you want the %d on\n",led_no);
  291.                             delay(delay_grade);
  292.                             ioctl(fd,IOCTL_LED_OFF,led_no);
  293.                    }
  294.     }
  295.     else if(!strcmp(argv[1],"right"))//turn off the led
  296.     {
  297.         for(i=0;i<20;i++)
  298.                    {
  299.                             if((i%2)==0)
  300.                             {
  301.                                      led_no = 1;
  302.                             }
  303.                             else
  304.                                      led_no = 2;
  305.                             ioctl(fd,IOCTL_LED_ON,led_no);
  306.                             delay(delay_grade);
  307.                             ioctl(fd,IOCTL_LED_OFF,led_no);
  308.                    }
  309.          }
  310.          else if(!strcmp(argv[1]),"both")
  311.          {
  312.                    for(i=0;i<50;i++)
  313.                    {
  314.                             ioctl(fd,IOCTL_LED_ON,1);
  315.                             ioctl(fd,IOCTL_LED_ON,2);
  316.                             delay(delay_grade);//delay 0.8s
  317.                             ioctl(fd,IOCTL_LED_OFF,1);
  318.                             ioctl(fd,IOCTL_LED_OFF,2);
  319.                             delay(delay_grade);//delay 0.8s
  320.                    }
  321.          }
  322.     else printf("error!\n");
  323.          close(fd);
  324.     return 0;
  325. }
  326. void delay(int time)
  327. {
  328.          while(time_1<time);
  329.          time_1 = 0; //you must clean the time_1 every time you sign a time
  330.          return;
  331. }
  332. void timer_init() //内核定时器初始化函数
  333. {
  334.          struct itimerval value; //(1)定义类型为itimerval的结构体变量
  335.          signal(SIGALRM, sigoutime);//注册信号的处理函数            
  336.          value.it_value.tv_sec = 0;//秒——设置第一次运行sigroutine函数时间
  337.          value.it_value.tv_usec = 100000;//微妙——设置为0
  338.          value.it_interval.tv_sec = 0;//秒——设置间隔运行sigroutine函数的时间(实际定时)
  339.          value.it_interval.tv_usec = 20000;//微妙———设置为20ms
  340.          setitimer(ITIMER_REAL, &value, NULL); //(2)设置 “真实计时器“参数
  341. }
  342. void sigoutime()
  343. {  
  344.          time_1++;
  345.          return;
  346. }
复制代码



jevin 发表于 2017-1-7 19:04:48 | 显示全部楼层
好东西,学习学习,收藏
jevin 发表于 2017-1-9 12:29:43 | 显示全部楼层
好东西,学习学习,收藏
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

i.MX8系列ARM cortex A53 M4 工控板上一条 /1 下一条

Archiver|手机版|小黑屋|天嵌 嵌入式开发社区 ( 粤ICP备11094220号 )

GMT+8, 2024-4-29 23:00 , Processed in 1.062500 second(s), 21 queries .

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表