|
TQ210 LED驱动及测试
1. 编写led驱动
1.1 在系统中创建目录/home/share/led/
#mkdir –p /home/share/led
进入led目录
#cd /home/share/led
1.2创建源码文件led_driver.c
#vim led_driver.c
源码内容见附件一。
保存退出.
1.3创建并编辑Makefile
在该目录下创建Makefile文件,将驱动程序编译成模块。
#vim Makefile
内容如下:- oj-m +=led_driver.o
- CURRENT_PATH := /home/share/led
- LINUX_KERNEL ?= /home/share/learning/linux-2.6.35
- #LINUX_KERNEL_PATH := $(LINUX_KERNEL)
- default:
- $(MAKE) -C $(LINUX_KERNEL) m=$(CURRENT_PATH) modules
- clean:
- $(MAKE) -C $(LINUX_KERNEL) M=$(CURRENT_PATH) clean
复制代码 . 编译
TQ210使用天嵌提供交叉编译器,路径:/home/share/tmp/opt/EmbedSky/4.4.6/bin
在该目录下直接make即可
#make
3. 测试led驱动
测试代码:见附件二
使用交叉编译工具编译程序:- # arm-linux-gcc -o led_test led_test.c
复制代码 将生成的可执行程序led_test复制到nfs文件系统/home/share/nfsboot/rootfs中/mnt目录下;
在超级终端上控制开发板。
挂载好nfs文件系统:- #mount –t nfs 10.10.84.41:/home/share/nfsboot/rootfs –o nolock /mnt
复制代码 进入挂载在/mnt 目录下的nfs文件系统内并且进入内部/mnt目录下:
#cd /mnt //此目录是开发版的子目录
#cd /mnt //此目录是挂载的宿主机上的nfs文件系统的子目录
执行可执行文件:
# ./led_test
出现段错误提示,原因参数不正确,还需要输入led的序号,以及开关指令。测试程序没有做好参数检查,所以会段错误在代码中对argc进行判断即可。
#./led_test 2 on //打开第二个led
#./led_test 2 off //关掉第二个led
开发板上两个LED灯均能正确控制,至此led驱动及测试代码试验完成。
附件一led驱动源码
TQ210 LED驱动及测试
1. 编写led驱动
1.1 在系统中创建目录/home/share/led/
#mkdir –p /home/share/led
进入led目录
#cd /home/share/led
1.2创建源码文件led_driver.c
#vim led_driver.c
源码内容见附件一。
保存退出.
1.3创建并编辑Makefile
在该目录下创建Makefile文件,将驱动程序编译成模块。
#vim Makefile
内容如下:
oj-m +=led_driver.o
CURRENT_PATH := /home/share/led
LINUX_KERNEL ?= /home/share/learning/linux-2.6.35
#LINUX_KERNEL_PATH := $(LINUX_KERNEL)
default:
$(MAKE) -C $(LINUX_KERNEL) m=$(CURRENT_PATH) modules
clean:
$(MAKE) -C $(LINUX_KERNEL) M=$(CURRENT_PATH) clean
2. 编译
TQ210使用天嵌提供交叉编译器,路径:/home/share/tmp/opt/EmbedSky/4.4.6/bin
在该目录下直接make即可
#make
3. 测试led驱动
测试代码:见附件二
使用交叉编译工具编译程序:
# arm-linux-gcc -o led_test led_test.c
将生成的可执行程序led_test复制到nfs文件系统/home/share/nfsboot/rootfs中/mnt目录下;
在超级终端上控制开发板。
挂载好nfs文件系统:
#mount –t nfs 10.10.84.41:/home/share/nfsboot/rootfs –o nolock /mnt
进入挂载在/mnt 目录下的nfs文件系统内并且进入内部/mnt目录下:
#cd /mnt //此目录是开发版的子目录
#cd /mnt //此目录是挂载的宿主机上的nfs文件系统的子目录
执行可执行文件:
# ./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的亮,灭。
* 调用实例:
* 提供控制台,命令式的测试程序。
*- #include <linux/miscdevice.h>
- #include <linux/input.h>
- #include <linux/clk.h>
- #include <linux/delay.h>
- #include <asm/io.h>
- #include <asm/uaccess.h>
- #include <mach/map.h>
- #include <mach/gpio.h>
- //#include <mach/gpio-bank.h>
- #include <mach/regs-gpio.h>
- #include <plat/gpio-core.h>
- #include <plat/gpio-cfg.h>
- #include <plat/gpio-cfg-helpers.h>
- #define DEVICE_NAME "led"
- /* 应用程序执行ioctl(fd, cmd, arg)时的第2个参数 */
- /*the second parameter that application program execute*/
- #define IOCTL_GPIO_ON 1
- #define IOCTL_GPIO_OFF 0
- /* 用来指定LED所用的GPIO引脚 */
- /*appoint the pin the LED will use*/
- static unsigned long gpio_table [] =
- {
- S5PV210_GPC0(3),
- S5PV210_GPC0(4),
- };
- /* 用来指定GPIO引脚的功能:输出 */
- /*appoint the function of the pin:out put*/
- static unsigned int gpio_cfg_table [] =
- {
- S3C_GPIO_SFN(1),
- S3C_GPIO_SFN(1),
- };
- //static char gpio_name[][]={{"GPC0_3"},{"GPC0_4"}};
- #ifdef CONFIG_TQ210_DEBUG_LEDS
- static void tq210_debug_leds(unsigned int cmd,unsigned long arg)
- {
- gpio_direction_output(gpio_table[arg], cmd);
- //s3c_gpio_setpin(gpio_table[arg], cmd);
- }
- static void toggle_led(unsigned int cmd,unsigned long arg)
- {
- int loop=0;
- printk("%s : led %ld toggle now: \n",__func__,arg);
- for(;loop<11;loop++)
- { cmd = loop%2;
- printk("leds %d %s \n",arg+1,(cmd)?"on":"o ff");
- tq210_debug_leds(cmd,arg);
- mdelay(1000);
- }
- }
- #endif
- /**
- *函数功能:打开/dev/led设备,设备名是:/dev/led
- *fuction:open /dev/led device ,devce name: /dev/led
- **/
- static int tq210_gpio_open(struct inode *inode, struct file *file)
- {
- int i;
- int err;
- err = gpio_request(gpio_table[0], "GPC0_3");
- if(err)
- {
- printk(KERN_ERR "failed to request GPC0_3 for LVDS PWDN pin\n");
- return err;
- }
- err = gpio_request(gpio_table[1], "GPC0_4");
- if(err)
- {
- printk(KERN_ERR "failed to request GPC0_4 for LVDS PWDN pin\n");
- return err;
- }
- printk(KERN_INFO " leds opened\n");
- for (i = 0; i < sizeof(gpio_table)/sizeof(unsigned long); i++)
- {
- s3c_gpio_cfgpin(gpio_table, gpio_cfg_table);
- gpio_direction_output(gpio_table, 0);
- //s3c_gpio_setpin(gpio_table, 0);
- }
- #ifdef CONFIG_TQ210_DEBUG_LEDS
- for (i = 0; i < sizeof(gpio_table)/sizeof(unsigned long); i++)
- {
- toggle_led(1,i);
- }
- #endif
- return 0;
- }
- /**
- *函数功能:用于控制led的亮灭
- *fuction:control the led /turn on & turn off
- *控制字为cmd,arg为控制哪个灯的亮灭取值范围为0-1:cmd为IOCTL_GPIO_ON时亮,cmd为IOCTL_GPIO_OFF为灭
- *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.
- **/
- static long tq210_gpio_ioctl(
- struct inode *inode,
- struct file *file,
- unsigned int cmd,
- unsigned long arg)
- {
- arg -= 1;
- if (arg > sizeof(gpio_table)/sizeof(unsigned long))
- {
- return -EINVAL;
- }
- switch(cmd)
- {
- case IOCTL_GPIO_ON:
- // 设置指定引脚的输出电平为1
- gpio_direction_output(gpio_table[arg], 1);
- //s3c_gpio_setpin(gpio_table[arg], 1);
- return 0;
- case IOCTL_GPIO_OFF:
- // 设置指定引脚的输出电平为0
- gpio_direction_output(gpio_table[arg], 0);
- //s3c_gpio_setpin(gpio_table[arg], 0);
- return 0;
- default:
- return -EINVAL;
- }
- }
- static int tq210_gpio_close(struct inode *inode, struct file *file)
- {
- gpio_free(gpio_table[0]);
- gpio_free(gpio_table[1]);
- printk(KERN_INFO "TQ210 LEDs driver successfully close\n");
- return 0;
- }
- /*驱动接口设置*/
- /*setting the interface of the driver*/
- static struct file_operations dev_fops = {
- .owner = THIS_MODULE,
- .ioctl = tq210_gpio_ioctl,
- .open = tq210_gpio_open,
- .release = tq210_gpio_close,
- };
- /*设备结构的设置*/
- /*setting the architecture of the device*/
- static struct miscdevice misc = {
- .minor = MISC_DYNAMIC_MINOR,
- .name = DEVICE_NAME,
- .fops = &dev_fops,
- };
- /*初始化设备,配置对应的IO,以及注册设备*/
- /*init the device, config the right IO and register the device*/
- static int __init dev_init(void)
- {
- int ret;
- int i;
- int err;
- #ifdef CONFIG_TQ210_DEBUG_LEDS
- err = gpio_request(gpio_table[0], "GPC0_3");
- if(err)
- {
- printk(KERN_ERR "failed to request GPC0_3 for LVDS PWDN pin\n");
- return err;
- }
- err = gpio_request(gpio_table[1], "GPC0_4");
- if(err)
- {
- printk(KERN_ERR "failed to request GPC0_4 for LVDS PWDN pin\n");
- return err;
- }
- for (i = 0; i < sizeof(gpio_table)/sizeof(unsigned long); i++)
- {
- //gpio_request(gpio_table[0],gpio_name);
- s3c_gpio_cfgpin(gpio_table, gpio_cfg_table);//配置管脚为输出config the pin to out put
- gpio_direction_output(gpio_table, 0);
- //s3c_gpio_setpin(gpio_table, 0);//设置管脚为低电平config the pin to low level
- s3c_gpio_setpull(gpio_table, S3C_GPIO_PULL_NONE);
- }
- #endif
- ret = misc_register(&misc);
- printk(KERN_INFO "TQ210 LEDs driver successfully probed\n");
- #ifdef CONFIG_TQ210_DEBUG_LEDS
- for (i = 0; i < sizeof(gpio_table)/sizeof(unsigned long); i++)
- {
- toggle_led(1,i);
- }
- #endif
- return ret;
- }
- /*注销设备*/
- /*log out the device*/
- static void __exit dev_exit(void)
- {
- misc_deregister(&misc);
- gpio_free(gpio_table[0]);
- gpio_free(gpio_table[1]);
- printk(KERN_INFO "TQ210 LEDs driver successfully exit\n");
- }
- module_init(dev_init);
- module_exit(dev_exit);
- MODULE_LICENSE("GPL");
- MODULE_AUTHOR("www.embedsky.com");
- MODULE_DESCRIPTION("LEDS' Driver");
- 附件二 led测试源码
- /*FILENAME:led_test.c
- *AUTHOR:Michael Li
- *DATE:2013-06-03
- *DESCRIPTION:the test of the led driver
- * */
- #include<stdio.h>
- #include<fcntl.h>
- #define DEVICENAME "/dev/led"
- #define IOCTL_LED_ON 1
- #define IOCTL_LED_OFF 0
- int main(int argc, char **argv)
- {
- FILE *fd;
- int led_no = 0;
- fd = (FILE *)open(DEVICENAME,0);
- if(argc < 3)
- {
- printf("The arguments you input are wrong\n");
- printf("USE:\n");
- printf("\t\t./program\tled-number\ton/off\n");
- return -1;
- }
- //led_no = strtoul(argv[1],0,0) -1;//its wrong to set like this
- led_no = strtoul(argv[1],0,0);//operate the led_1 by input 1 and led_2 by input 2
- printf("111111\n");
- if(!strcmp(argv[2],"on"))//turn on the led
- {
- ioctl(fd,IOCTL_LED_ON,led_no);
- printf("you want the %d on\n",led_no);
- }
- else if(!strcmp(argv[2],"off"))//turn off the led
- {
- ioctl(fd,IOCTL_LED_OFF,led_no);
- }
- else printf("error!\n");
- return 0;
- }
- 附件三:流水灯
- /*FILENAME:led_test.c
- *AUTHOR:Michael Li
- *DATE:2013-06-03
- *DESCRIPTION:the test of the led driver,please refer to the label "usage:" below.
- * */
- #include<stdio.h>
- #include<fcntl.h>
- #include <signal.h>
- //#include <time.h>
- #include <sys/time.h>
- #define DEVICENAME "/dev/led"
- #define IOCTL_LED_ON 1
- #define IOCTL_LED_OFF 0
- void sigoutime();
- void timer_init();
- void delay(int time);
- int time_1= 0;
- int main(int argc, char **argv)
- {
- FILE *fd;
- int led_no = 0;
- int i = 0;
- fd = (FILE *)open(DEVICENAME,0);
- int delay_grade = 0;
- timer_init();
- usage:
- if(argc < 3)
- {
- printf("The arguments you input are wrong\n");
- printf("USE:\n");
- printf("\t./program\t<right/left/both>\t<1/2/3>\n");
- printf("\t3:slow;2:faster;1:fastest\n");
- printf("\teg: ./led_flow\tleft\t1\n\tlet the led light start from left and the speed is the fastest\n");
- return -1;
- }
-
- if(!strcmp(argv[2],"1"))
- delay_grade = 1;//20ms
- else if (!(argv[2],"2"))
- delay_grade = 15;//300ms
- else if(!(argv[2],"3"))
- delay_grade = 50;//1s
- else
- delay_grade = 30;//600ms
-
- if(!strcmp(argv[1],"left"))//turn on the led
- {
- for(i=0;i<40;i++)
- {
- if((i%2)!=0)
- {
- led_no = 1;
- }
- else
- led_no = 2;
- ioctl(fd,IOCTL_LED_ON,led_no);
- printf("you want the %d on\n",led_no);
- delay(delay_grade);
- ioctl(fd,IOCTL_LED_OFF,led_no);
- }
- }
- else if(!strcmp(argv[1],"right"))//turn off the led
- {
- for(i=0;i<20;i++)
- {
- if((i%2)==0)
- {
- led_no = 1;
- }
- else
- led_no = 2;
- ioctl(fd,IOCTL_LED_ON,led_no);
- delay(delay_grade);
- ioctl(fd,IOCTL_LED_OFF,led_no);
- }
- }
- else if(!strcmp(argv[1]),"both")
- {
- for(i=0;i<50;i++)
- {
- ioctl(fd,IOCTL_LED_ON,1);
- ioctl(fd,IOCTL_LED_ON,2);
- delay(delay_grade);//delay 0.8s
- ioctl(fd,IOCTL_LED_OFF,1);
- ioctl(fd,IOCTL_LED_OFF,2);
- delay(delay_grade);//delay 0.8s
- }
- }
- else printf("error!\n");
- close(fd);
- return 0;
- }
- void delay(int time)
- {
- while(time_1<time);
- time_1 = 0; //you must clean the time_1 every time you sign a time
- return;
- }
- void timer_init() //内核定时器初始化函数
- {
- struct itimerval value; //(1)定义类型为itimerval的结构体变量
- signal(SIGALRM, sigoutime);//注册信号的处理函数
- value.it_value.tv_sec = 0;//秒——设置第一次运行sigroutine函数时间
- value.it_value.tv_usec = 100000;//微妙——设置为0
- value.it_interval.tv_sec = 0;//秒——设置间隔运行sigroutine函数的时间(实际定时)
- value.it_interval.tv_usec = 20000;//微妙———设置为20ms
- setitimer(ITIMER_REAL, &value, NULL); //(2)设置 “真实计时器“参数
- }
- void sigoutime()
- {
- time_1++;
- return;
- }
复制代码 |
|