Linux内核---56.gpio控制

本文介绍MTK平台上的GPIO控制方法,包括内核配置、应用层控制及通过sysfs接口实现GPIO状态改变的过程。提供了具体代码示例和测试步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一.mtk平台的gpio控制
1.1 内核中的gpio配置
//设置gpio18为GPIO模式
mt_set_gpio_mode(GPIO18, GPIO_MODE_GPIO);  
//设置gpio18方向为out
mt_set_gpio_dir(GPIO18, GPIO_DIR_OUT);
//设置gpio18高
mt_set_gpio_out(GPIO18, GPIO_OUT_ONE);  //低是ZERO
1.2 上层应用控制gpio的高低
  1. cong@msi:/work/mtk/temp/gpiotest$ cat gpiotest.
  2. #include <stdio.h>
  3. #include <fcntl.h>
  4. #include <sys/types.h>
  5. #include <sys/stat.h>
  6. #include <sys/time.h>
  7. #include <dirent.h>
  8. #include <unistd.h>
  9. #include <string.h>
  10. #include <sys/ioctl.h>
  11. #include <linux/ioctl.h>

  12. #define dbmsg(fmt, args ...) printf("%s:%s[%d]: "fmt"\n", __FILE__,__FUNCTION__, __LINE__,##args)

  13. #define GPIO_IOC_MAGIC 0x90
  14. #define GPIO_IOCQMODE _IOR(GPIO_IOC_MAGIC, 0x01, uint32_t)
  15. #define GPIO_IOCTMODE0 _IOW(GPIO_IOC_MAGIC, 0x02, uint32_t)
  16. #define GPIO_IOCTMODE1 _IOW(GPIO_IOC_MAGIC, 0x03, uint32_t)
  17. #define GPIO_IOCTMODE2 _IOW(GPIO_IOC_MAGIC, 0x04, uint32_t)
  18. #define GPIO_IOCTMODE3 _IOW(GPIO_IOC_MAGIC, 0x05, uint32_t)
  19. #define GPIO_IOCQDIR _IOR(GPIO_IOC_MAGIC, 0x06, uint32_t)
  20. #define GPIO_IOCSDIRIN _IOW(GPIO_IOC_MAGIC, 0x07, uint32_t)
  21. #define GPIO_IOCSDIROUT _IOW(GPIO_IOC_MAGIC, 0x08, uint32_t)
  22. #define GPIO_IOCQPULLEN _IOR(GPIO_IOC_MAGIC, 0x09, uint32_t)
  23. #define GPIO_IOCSPULLENABLE _IOW(GPIO_IOC_MAGIC, 0x0A, uint32_t)
  24. #define GPIO_IOCSPULLDISABLE _IOW(GPIO_IOC_MAGIC, 0x0B, uint32_t)
  25. #define GPIO_IOCQPULL _IOR(GPIO_IOC_MAGIC, 0x0C, uint32_t)
  26. #define GPIO_IOCSPULLDOWN _IOW(GPIO_IOC_MAGIC, 0x0D, uint32_t)
  27. #define GPIO_IOCSPULLUP _IOW(GPIO_IOC_MAGIC, 0x0E, uint32_t)
  28. #define GPIO_IOCQINV _IOR(GPIO_IOC_MAGIC, 0x0F, uint32_t)
  29. #define GPIO_IOCSINVENABLE _IOW(GPIO_IOC_MAGIC, 0x10, uint32_t)
  30. #define GPIO_IOCSINVDISABLE _IOW(GPIO_IOC_MAGIC, 0x11, uint32_t)
  31. #define GPIO_IOCQDATAIN _IOR(GPIO_IOC_MAGIC, 0x12, uint32_t)
  32. #define GPIO_IOCQDATAOUT _IOR(GPIO_IOC_MAGIC, 0x13, uint32_t)
  33. #define GPIO_IOCSDATALOW _IOW(GPIO_IOC_MAGIC, 0x14, uint32_t)
  34. #define GPIO_IOCSDATAHIGH _IOW(GPIO_IOC_MAGIC, 0x15, uint32_t)
  35.     
  36. int main ( int argc, char *argv[] )
  37. {
  38.     int fd_gpio;
  39.     int ret;
  40.     
  41.     fd_gpio = open("/dev/mtgpio",O_RDWR);
  42.     if(fd_gpio < 0)
  43.     {
  44.      printf("fd_gpio open error\n");
  45.         return -1;
  46.     }

  47.     while(1)
  48.     {
  49.         ret = ioctl(fd_gpio, GPIO_IOCSDATAHIGH, 18);
  50.         sleep(1);
  51.         ret = ioctl(fd_gpio, GPIO_IOCSDATAHIGH, 18);
  52.         sleep(1);
  53.     }

  54.     close(fd_gpio);
  55.     return 0;
  56. }
1.3 应用代码
  gpiotest.rar  (下载后改名为gpiotest.tar.gz)
1.4 查看gpio状态
/sys/class/misc/mtgpio/pin
  1. 130|root@78P01:/ # cat /sys/class/misc/mtgpio/pin 
  2. PIN: [MODE] [PULL_SEL] [DIN] [DOUT] [PULL EN] [DIR] [IES]
  3. 3: 3 0 0 0 0 0 1 MI                  -->MODE这一项就是在code.dws中配的MODE
  4. 4: 3 0 0 0 0 1 1 MO
  5. 5: 3 0 1 0 0 1 1 CS
  6. 6: 3 0 0 0 0 1 1 CLK

二.利用sys控制gpio口
2.1 代码如下
  1. #include <linux/init.h>
  2. #include <linux/module.h>
  3. #include <linux/device.h>
  4. #include <linux/ioport.h>
  5. #include <linux/errno.h>
  6. #include <linux/workqueue.h>
  7. #include <linux/platform_device.h>
  8. #include <linux/types.h>
  9. #include <linux/io.h>
  10. #include <mach/mt_gpio.h>

  11. #define GPIO_POWER_EN GPIO123 //

  12. typedef struct {
  13.     int gpio_power;
  14. }hello_priv;

  15. static ssize_t hello_set_power(struct device *dev,struct device_attribute *attr,const char *buf, size_t count)
  16. {
  17.     hello_priv* prv = dev_get_drvdata(dev);
  18.     if ('0' == buf[0]) //shutdown
  19.     { //process: pin low-->high
  20.      mt_set_gpio_out(prv->gpio_power, GPIO_OUT_ZERO);
  21.       msleep(1500);
  22.       mt_set_gpio_out(prv->gpio_power, GPIO_OUT_ONE);
  23.       printk(KERN_NOTICE "cong: %s:%s[%d]: buf=%s", __FILE__,__FUNCTION__, __LINE__,buf); 
  24.     }else if ('1' == buf[0]) //poweron
  25.     { //process: power pin high --> low
  26.      mt_set_gpio_out(prv->gpio_power, GPIO_OUT_ONE);
  27.       msleep(1500);
  28.       mt_set_gpio_out(prv->gpio_power, GPIO_OUT_ZERO);
  29.       printk(KERN_NOTICE "cong: %s:%s[%d]: buf=%s", __FILE__,__FUNCTION__, __LINE__,buf); 
  30.     }
  31.     return count;
  32. }

  33. static DEVICE_ATTR(power_on, S_IRUGO | S_IWUSR,NULL, hello_set_power);

  34. static struct attribute *hello_attributes[] = {
  35.     &dev_attr_power_on.attr,
  36.     NULL
  37. };

  38. static const struct attribute_group hello_attr_group = {
  39.     .attrs = hello_attributes,
  40. };

  41. static int __init hello_probe(struct platform_device *pdev)
  42. {
  43.     int rc;
  44.     hello_priv* prv;

  45.     prv = devm_kzalloc(&pdev->dev, sizeof(hello_priv), GFP_KERNEL);
  46.     if (!prv) {
  47.         dev_err(&pdev->dev, "failed to allocate hello\n");
  48.         return -ENOMEM;
  49.     }

  50.     prv->gpio_power = GPIO_POWER_EN ;

  51.     mt_set_gpio_mode(prv->gpio_power, GPIO_MODE_GPIO);

  52.     mt_set_gpio_dir(prv->gpio_power, GPIO_DIR_OUT);
  53.     platform_set_drvdata(pdev,prv);

  54.     rc = sysfs_create_group(&pdev->dev.kobj, &hello_attr_group);
  55.     if (rc) {
  56.         dev_err(&pdev->dev,"failed to create hello sysfs group\n");
  57.         goto fail;
  58.     }

  59.     return 0;
  60. fail:
  61.     return rc;
  62. }

  63. struct platform_driver hello_driver = {
  64.     .driver = {
  65.         .name = "hello",
  66.         .owner = THIS_MODULE,
  67.     },
  68.     .probe = hello_probe,
  69. };

  70. static struct platform_device hello_device =
  71. {
  72.     .name = "hello",
  73.     .id = -1,
  74. };

  75. static int __init hello_init(void)
  76. {
  77.     int ret;

  78.     ret = platform_device_register(&hello_device);
  79.     if (ret != 0)
  80.       printk(KERN_NOTICE "cong: %s:%s[%d]: error", __FILE__,__FUNCTION__, __LINE__); 

  81.     ret = platform_driver_register(&hello_driver);
  82.     return ret;
  83. }

  84. static void __init hello_exit(void)
  85. {
  86.     platform_driver_unregister(&hello_driver);
  87. }

  88. module_init(hello_init);
  89. module_exit(hello_exit);

  90. MODULE_DESCRIPTION("GPIO Controller Driver");
  91. MODULE_AUTHOR("cong");
  92. MODULE_LICENSE("GPL");
2.2 则可以在
echo 1 > /sys/devices/platform/hello/power_on
2.3 测试的应用程序如下:
  1. #include <stdio.h>
  2. #include <fcntl.h>
  3. #include <sys/types.h>
  4. #include <sys/stat.h>
  5. #include <sys/time.h>
  6. #include <unistd.h>
  7. #include <string.h>
  8. #include <sys/ioctl.h>
  9. #include <linux/ioctl.h>
  10. #include <sys/types.h>
  11. #include <sys/stat.h>
  12. #include <fcntl.h>

  13. #define dbmsg(fmt, args ...) printf("%s:%s[%d]: "fmt"\n", __FILE__,__FUNCTION__, __LINE__,##args)    

  14. #define POWER_ON "power_on"

  15. int usage()
  16. {
  17.     printf("usage:\n");
  18.     printf("./test power_on <0/1> : 0-->poweron; 1-->poweroff \n"); 
  19.     return 0;
  20. }

  21. int power_on(char* arg)
  22. {
  23.     int fd;
  24.     if( ('0'!=arg[0]) && ('1'!=arg[0]))
  25.     {
  26.         dbmsg("bad args");
  27.         return -1;
  28.     }
  29.     fd = open("/sys/devices/platform/hello/power_on", O_RDWR);
  30.     if(fd < 0)
  31.     {
  32.         dbmsg("open error");
  33.         return -1;
  34.     }
  35.     dbmsg("arg=%s", arg);
  36.     write(fd, arg, 1);
  37.     return 0;
  38. }

  39. int main ( int argc, char *argv[] )
  40. {
  41.     int ret;
  42.     int num;
  43.     int fd_gpio;
  44.     if(argc < 2)
  45.     {
  46.         usage();
  47.         return -1;
  48.     }

  49.     if(strncmp(argv[1],POWER_ON, sizeof(POWER_ON)) == 0)
  50.     {
  51.         dbmsg("%s", POWER_ON);
  52.         if(argc != 3)
  53.         {
  54.             usage();
  55.             return -1;
  56.         }
  57.         power_on(argv[2]); 
  58.     }
  59.     return 0;
  60. }
2.4 测试过程
  1. root@cong:/home/cong/driver/app# ./test power_on 0
  2. test.c:main[57]: power_on
  3. test.c:power_on[39]: arg=0
  4. root@cong:/home/cong/driver/app# ./test power_on 1
  5. test.c:main[57]: power_on
  6. test.c:power_on[39]: arg=1

``` /include/ "system-conf.dtsi" #include <dt-bindings/gpio/gpio.h> #include <dt-bindings/input/input.h> #include <dt-bindings/media/xilinx-vip.h> #include <dt-bindings/phy/phy.h> / { model = "Alientek Navigator Zynq Development Board"; compatible = "xlnx,zynq-zc702", "xlnx,zynq-7000"; leds { compatible = "gpio-leds"; gpio-led1 { label = "led2"; gpios = <&gpio0 0 GPIO_ACTIVE_HIGH>; default-state = "on"; }; gpio-led2 { label = "led1"; gpios = <&gpio0 54 GPIO_ACTIVE_HIGH>; linux,default-trigger = "heartbeat"; }; gpio-led3 { label = "pl_led0"; gpios = <&axi_gpio_0 0 0 GPIO_ACTIVE_HIGH>; default-state = "on"; }; gpio-led4 { label = "pl_led1"; gpios = <&axi_gpio_0 1 0 GPIO_ACTIVE_HIGH>; linux,default-trigger = "timer"; }; gpio-led5 { label = "ps_led0"; gpios = <&gpio0 7 GPIO_ACTIVE_HIGH>; default-state = "on"; }; gpio-led6 { label = "ps_led1"; gpios = <&gpio0 8 GPIO_ACTIVE_HIGH>; linux,default-trigger = "timer"; }; }; keys { compatible = "gpio-keys"; autorepeat; gpio-key1 { label = "pl_key0"; gpios = <&gpio0 55 GPIO_ACTIVE_LOW>; linux,code = <KEY_LEFT>; gpio-key,wakeup; autorepeat; }; gpio-key2 { label = "pl_key1"; gpios = <&gpio0 56 GPIO_ACTIVE_LOW>; linux,code = <KEY_RIGHT>; gpio-key,wakeup; autorepeat; }; gpio-key3 { label = "ps_key1"; gpios = <&gpio0 12 GPIO_ACTIVE_LOW>; linux,code = <KEY_UP>; gpio-key,wakeup; autorepeat; }; gpio-key4 { label = "ps_key2"; gpios = <&gpio0 11 GPIO_ACTIVE_LOW>; linux,code = <KEY_DOWN>; gpio-key,wakeup; autorepeat; }; touch-key { label = "touch_key"; gpios = <&gpio0 57 GPIO_ACTIVE_HIGH>; linux,code = <KEY_ENTER>; gpio-key,wakeup; autorepeat; }; }; beep { compatible = "gpio-beeper"; gpios = <&gpio0 58 GPIO_ACTIVE_HIGH>; }; usb_phy0: phy0@e0002000 { compatible = "ulpi-phy"; #phy-cells = <0>; reg = <0xe0002000 0x1000>; view-port = <0x0170>; drv-vbus; }; }; &uart0 { u-boot,dm-pre-reloc; status = "okay"; }; &sdhci0 { u-boot,dm-pre-reloc; status = "okay"; }; &usb0 { dr_mode = "otg"; usb-phy = <&usb_phy0>; }; &qspi { u-boot,dm-pre-reloc; flash@0 { /* 16 MB */ compatible = "w25q256", "jedec,spi-nor"; reg = <0x0>; spi-max-frequency = <50000000>; #address-cells = <1>; #size-cells = <1>; partition@0x00000000 { label = "boot"; reg = <0x00000000 0x00100000>; }; partition@0x00100000 { label = "bootenv"; reg = <0x00100000 0x00020000>; }; partition@0x00120000 { label = "bitstream"; reg = <0x00120000 0x00400000>; }; partition@0x00520000 { label = "device-tree"; reg = <0x00520000 0x00020000>; }; partition@0x00540000 { label = "kernel"; reg = <0x00540000 0x00500000>; }; partition@0x00A40000 { label = "space"; reg = <0x00A40000 0x00000000>; }; }; }; &gem0 { local-mac-address = [00 0a 35 00 8b 87]; phy-handle = <&ethernet_phy>; ethernet_phy: ethernet-phy@7 { /* yt8521 */ reg = <0x7>; device_type = "ethernet-phy"; }; }; &gem1 { local-mac-address = [00 0a 35 00 11 55]; phy-reset-gpio = <&gpio0 63 GPIO_ACTIVE_LOW>; phy-reset-active-low; phy-handle = <&pl_phy>; pl_phy: pl_phy@4 { reg = <0x4>; device_type = "ethernet-phy"; }; }; &watchdog0 { status = "okay"; reset-on-timeout; // Enable watchdog reset function }; &adc { status = "okay"; xlnx,channels { #address-cells = <1>; #size-cells = <0>; channel@0 { reg = <0>; }; }; }; &i2c0 { clock-frequency = <100000>; eeprom@50 { compatible = "atmel,24c64"; reg = <0x50>; pagesize = <32>; }; rtc@51 { compatible = "nxp,pcf8563"; reg = <0x51>; }; };```如何查看linux内核支持哪些驱动
最新发布
03-14
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值