|
各位版友們好,
在寫GPIO練習的時候遇上一些問題,還請高手幫忙看一下。因為想提供多一點細節,文長還請多包涵。
想要達成的目的是GPH3_0輸出高電平,利用GPH3_3監看輸入電平,然後在ioctl內多出IOCTL_GPIO_READ的操作,其他架構跟LED範例手冊內的相同。
程式碼如下:
- /* use led sample to test GPH3 is fine under control */
- /* run a complete LED sample, just change pins! */
- #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 "led3" /* change the name! */
- enum{
- IOCTL_GPIO_ON = 0,
- IOCTL_GPIO_READ,
- IOCTL_GPIO_OFF,
- };
- //#define IOCTL_GPIO_ON 0
- //#define IOCTL_GPIO_OFF 1
- //#define IOCTL_GPIO_READ 2
- static unsigned long gpio_table [] =
- {
- S5PV210_GPH3(1), /* output, KP_ROW1, have voltage change */
- S5PV210_GPH3(3), /* input, KP_ROW3 */
- };
- static unsigned int gpio_cfg_table [] =
- {
- // S3C_GPIO_SFN(1),
- // S3C_GPIO_SFN(1),
- S3C_GPIO_SFN(1),
- S3C_GPIO_SFN(0),
- };
- static int tq210_gpio_open(struct inode *inode, struct file *file)
- {
- int i;
- int err;
- err = gpio_request(gpio_table[0], "GPH3_1");
- if(err)
- {
- printk(KERN_ERR "failed to request GPH3_1 for LVDS PWDN pin\n");
- return err;
- }
- err = gpio_request(gpio_table[1], "GPH3_3");
- if(err)
- {
- printk(KERN_ERR "failed to request GPH3_3 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[i], gpio_cfg_table[i]);
- // gpio_direction_output(gpio_table[i], 0);
- }
- gpio_direction_output(gpio_table[0], 0);
- gpio_direction_input(gpio_table[1]);
- return 0;
- }
- static long tq210_gpio_ioctl(
- struct file *file,
- unsigned int cmd,
- unsigned long arg)
- {
- int res;
-
- printk(KERN_INFO "+%s, cmd = %hd\n", __func__, cmd);
-
- arg -= 1;
- if (arg > sizeof(gpio_table)/sizeof(unsigned long))
- {
- printk(KERN_INFO "error! ");
- return -EINVAL;
- }
- switch(cmd)
- {
- case IOCTL_GPIO_ON:
- printk(KERN_INFO "[OUTPUT] HIGH ");
- gpio_direction_output(gpio_table[arg], 1);
- return 0;
- case IOCTL_GPIO_OFF:
- printk(KERN_INFO "[OUTPUT] LOW ");
- gpio_direction_output(gpio_table[arg], 0);
- return 0;
- case IOCTL_GPIO_READ:
- res = gpio_get_value(gpio_table[arg]);
- if (res < 0){
- printk(KERN_INFO "(X) Fail");
- }else if(res == 0){
- printk(KERN_INFO "[INPUT] LOW ");
- }else{
- printk(KERN_INFO "[INPUT] HIGH");
- }
- 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;
- }
- static struct file_operations dev_fops = {
- .owner = THIS_MODULE,
- .unlocked_ioctl = tq210_gpio_ioctl,
- .open = tq210_gpio_open,
- .release = tq210_gpio_close,
- };
- static struct miscdevice misc = {
- .minor = MISC_DYNAMIC_MINOR,
- .name = DEVICE_NAME,
- .fops = &dev_fops,
- };
- static int __init dev_init(void)
- {
- int ret;
- ret = misc_register(&misc);
- if(ret == 0)
- printk(KERN_INFO "TQ210 LEDs driver successfully probed\n");
- return ret;
- }
- 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("Paul <shufexiu@163.com>");
- MODULE_DESCRIPTION("LEDS' Driver");
复制代码
測試用之應用程式的主要流程:open->LED1輸出高電平->讀取LED2腳位10次->LED2輸出低電平,期間可以手動插拔電線就可以改變電平,確認輸入值的變動。
程式碼如下:
- #include <stdio.h>
- #include <stdlib.h>
- #include <sys/types.h>
- #include <asm/types.h>
- #include <linux/fb.h>
- #include <linux/kernel.h>
- #include <linux/fs.h>
- #include <fcntl.h>
- #include<string.h>
- #include<unistd.h>
- #include<sys/mman.h>
- #include <sys/poll.h>
- #define DEV_FILE_NAME "/dev/led3"
- /* 应用程序执行ioctl(fd, cmd, arg)时的第2个参数 */
- /* #define IOCTL_GPIO_ON 0
- #define IOCTL_GPIO_OFF 1
- #define IOCTL_GPIO_READ 2 */
- enum{
- IOCTL_GPIO_ON = 0,
- IOCTL_GPIO_READ,
- IOCTL_GPIO_OFF,
- };
- #define LED1 1
- #define LED2 2
-
- int main(void)
- {
- int devfd;
- int i,err;
-
- devfd = open(DEV_FILE_NAME,O_RDWR);
- if(devfd < 0)
- {
- printf("can't open dev (%s)",DEV_FILE_NAME);
- return 0;
- }
- err = ioctl(devfd,IOCTL_GPIO_ON,LED1);
- if(err<0)
- printf("GPIO_ON faild! (%d)\n",err);
- sleep(1);
-
- for(i=0;i<10;++i)
- {
-
- err = ioctl(devfd,IOCTL_GPIO_READ,LED2);
- if(err<0)
- printf("GPIO_READ faild! (%d)\n",err);
- sleep(2);
- }
- err = ioctl(devfd,IOCTL_GPIO_OFF,LED1);//关闭LED1。
- if(err<0)
- printf("GPIO_OFF faild! (%d)\n",err);
- sleep(2); //休眠1S
-
- close(devfd);//关闭设备。对应驱动中的tq210_gpio_close
- return 0;
- }
复制代码
目前遇到的問題是,在最前面定義ioctl的cmd參數時,不曉得為什麼只能新增兩個參數,不管是用define或是enum,不管是從0開始還是從1開始,都會發生如下的狀況:
(一)參數從0開始
- enum{
- IOCTL_GPIO_ON = 0,
- IOCTL_GPIO_READ,
- IOCTL_GPIO_OFF,
- };
复制代码 則輸出如下圖,可以發現IOCTL_GPIO_ON(0)以及IOCTL_GPIO_READ(1)皆正常進入操作,而IOCTL_GPIO_OFF(2)則運行失敗...
(二)後來想把enum從1開始試試,
- enum{
- IOCTL_GPIO_ON = 1,
- IOCTL_GPIO_READ,
- IOCTL_GPIO_OFF,
- };
复制代码 卻是IOCTL_GPIO_ON(1)以及IOCTL_GPIO_OFF(3)正常運作,反而是夾在中間的IOCTL_GPIO_READ(2)無法進行操作
到底要怎麼修改才能加入新的操作呢...或是有哪裏使用了不正確的語法,還請各位大師們解惑,感激不盡~~
|
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有帐号?注册
x
|