ã«ãŒãã«ããŒãžã§ã³4.6-r1ãããgpioã«ãŒãã«ãµãã·ã¹ãã ãšå¯Ÿè©±ããããã®æ°ããã€ã³ã¿ãŒãã§ã€ã¹ãå©çšå¯èœã«ãªããŸããã çŸåšãgpioãæäœãããããããå²ã蟌ã¿ãååŸããå
¬åŒã®æ¹æ³ã3ã€ãããŸãã ãã®ãµãã·ã¹ãã ã®ããŒãºãæãäžããæå³ã¯ãããŸãããå°ããªéšåã¯éé
·ãªæ¥åžžç掻ã§ãããå¥ã®éšåã¯æ¥œãã趣å³ã§ããããã¹ãŠã®ç¹ã§çžäºäœçšã®æ°ããæ©äŒãã«ãŒãã«ã§æäŸãããŸããã
ãã®ããŒãã¯æ¬è³ªçã«äººæ°ããããŸãããªããªããã€ãããŒã·ã§ã³ã«äŒŽãäž»ãªå©ç¹ãã€ãŸãã«ãŒãã«ã®ã³ã³ããã¹ãã§gpioã䜿çšããäœæ¥ã®ç°¡çŽ åã«ã€ããŠã¯è§Šããªãããã§ãã
æ°ããuapi gpioã€ã³ã¿ãŒãã§ã€ã¹
https://github.com/torvalds/linux/blob/master/include/uapi/linux/gpio.h
ãŸãã gpiochipã¯å®éã«ã¯ããã€ã¹ã§ããã devfsã§ã¯gpiochipNãšããŠèŠãããšãã§ããŸããããã§ãNã¯åæåé åºã§å²ãåœãŠããããããçªå·ã§ãã 次ã«ããã¹ãŠã®æ§æã¯ioctlãä»ããŠè¡ãããŸã ã ãããŠç¬¬äžã«ãé©ãã¹ãããšã«ãèªã¿åããšæžã蟌ã¿ã¯ãç¹å¥ãªstruct gpiohandle_dataæ§é ã®å©ããåããŠãèªã¿åã/æžã蟌ã¿åŒã³åºãã«ãã£ãŠè¡ãããŸãã
gpio-mockup
ã«ãŒãã«ããŒãžã§ã³v4.9-rc1ïŒå®éã«ã¯v4.12-rc1ãããå€ãããŒãžã§ã³ã§ã®ã¿äœ¿çšå¯èœïŒä»¥éã debugfsã«ããç¶æ
管çããµããŒãããä»®æ³gpioããã€ã¹ãå©çšå¯èœã«ãªããŸããã
ããšãã°ããŠãŒã¶ãŒç©ºéã§ã®sysfsãšuapiã®éããèããŠã¿ãŸããã ã
gpio-mockupã®åæå
ãã©ã¡ãŒã¿ïŒ
- gpio_mockup_ranges-gpiochipsãåæåããæ°å€ã®ãã¢ã "baseãend"ã®åœ¢åŒã§ãbaseã¯éå§çªå·ãendã¯ç¯å²ã®çµäºã§ãã
- gpio_mockup_named_lines-ããŒã«å€ãã©ã¡ãŒã¿ãŒïŒèšå®ãããŠããå ŽåïŒã¯ãgpio-mockup-A..ZNã®åœ¢åŒã§åè¡ã«ã©ãã«ãå²ãåœãŠãŸããããã§ãNã¯éè¡ã®è¡ã®ã·ãªã¢ã«çªå·ã§ãã
ãã®ããŒã ã§ã¯ãç¯å²ã[0-8]ã[8,16ïŒã®8è¡ã®gpiochipã2ã€äœæããŸããã gpio_mockup_named_linesã«ã€ããŠã¯åŸã»ã©èª¬æããŸãã
sysfsãšuapiã®æ¯èŒ
æ°ãããã©ã€ããŒã䜿çšããŠããŠãŒã¶ãŒã®èŠ³ç¹ãã2ã€ã®ã·ã¹ãã ã®éããæ€èšããŸãã
sysfs
ãŠã¢ã
struct gpiochip_info chip_info; ioctl(fd, GPIO_GET_CHIPINFO_IOCTL, &chip_info);
è¡ãå
¥åãšããŠèšå®ããå€ãèªã¿åã
sysfs
ãŠã¢ã
struct gpiohandle_request req; req.lineoffsets[0] = 0; req.flags = GPIOHANDLE_REQUEST_INPUT; req.lines = 1; struct gpiohandle_data data; ioctl(fd, GPIO_GET_LINEHANDLE_IOCTL, &req); ioctl(req.fd, GPIOHANDLE_GET_LINE_VALUES_IOCTL, &data);
è¡ãåºåãšããŠèšå®ãã
sysfs
# echo high > /sys/class/gpio/gpio0/direction
ãŠã¢ã
struct gpiohandle_request req; req.lineoffsets[0] = 0; req.flags = GPIOHANDLE_REQUEST_OUTPUT; req.default_values[0] = 1; req.lines = 1; ioctl(fd, GPIO_GET_LINEHANDLE_IOCTL, &req);
ãšããžåŠç
sysfs
ãŠã¢ã
struct gpioevent_request ereq; ereq.lineoffset = 0; ereq.eventflags = GPIOEVENT_REQUEST_BOTH_EDGES; ioctl(fd, GPIO_GET_LINEEVENT_IOCTL, &ereq);
ã€ãã³ãã®ããŒãªã³ã°
sysfsã®ã«ãŒãã«ããã¥ã¡ã³ãã§ã¯ã EPOLLPRIããã³EPOLLERR ïŒãŸãã¯selectã®exceptfds ïŒã䜿çšããããšã瀺ãããŠããŸããããã¯ãååãšããŠã gpioãµãã·ã¹ãã ã§ã¯ãªãsysfs_notifyã®åŒã³åºãã§äžè¬çã§ãã
uapiã«ã¯ãEPOLLINã§ååã§ãã
struct epoll_event event; event.data.fd = ereq.fd; event.events = EPOLLIN; epoll_ctl(epollfd, EPOLL_CTL_ADD, ereq.fd, &event);
ã¿ã€ã ã¹ã¿ã³ãä»ãã®ã€ãã³ããèªã¿åããã¿ã€ãGPIOEVENT_EVENT_RISING_EDGEãŸãã¯GPIOEVENT_EVENT_FALLING_EDGEãå
¥åããŸãã
struct gpioevent_data event; read(pin->fd, &event, sizeof(event));
EPOLLET for uapi㯠ãepollã®ããã¥ã¡ã³ãã«åŸã£ãŠæ©èœããŸãã
ã©ãã«
誰ããæ
£ããŠããé£çµ¡å
ågpioNã¯äžè¬ã«æ£èŠã§ã¯ãããŸããããé£çµ¡å
ã«ååãä»ããããŠããªãå Žåãããšãã°ããã€ã¹ããªãŒã§äœ¿çšãããŸãã
// drivers/gpio/gpiolib-sysfs.c // int gpiod_export(struct gpio_desc *desc, bool direction_may_change) offset = gpio_chip_hwgpio(desc); if (chip->names && chip->names[offset]) ioname = chip->names[offset]; dev = device_create_with_groups(&gpio_class, &gdev->dev, MKDEV(0, 0), data, gpio_groups, ioname ? ioname : "gpio%u", desc_to_gpio(desc));
gpio_mockup_named_linesãªãã·ã§ã³ã䜿çšããŠgpio - mockupãè©ŠããŠã¿ãŸãããã
ã芧ã®ãšãããé£çµ¡å
åã¯gpio_chip_label - gpio_offsetã«ãªããŸããããããã¯gpio - mockup ãã©ã€ããŒã«ã®ã¿åœãŠã¯ãŸããŸãã
// drivers/gpio/gpio-mockup.c // static int gpio_mockup_name_lines(struct device *dev, struct gpio_mockup_chip *chip) for (i = 0; i < gc->ngpio; i++) names[i] = devm_kasprintf(dev, GFP_KERNEL, "%s-%d", gc->label, i);
uapiã䜿çšããã«é£çµ¡å
ã®ååãååšãããã©ãããäºåã«ãæšæž¬ãããããšã¯ã§ããŸããã ãŸã ãååãäºåã«ããããªãå Žåã¯ããšã¯ã¹ããŒãããããååä»ããè¡ãèŠã€ããããšã¯å°é£ã§ãïŒãããããã£ãŠããå Žåã¯ãæ確ãªèå¥ã®ããã«ãæ¢ç¥ã®ååãšãªãã»ãããå¿
èŠã§ãïŒ gpiochip ïŒã
ãŠã¢ã
uapiã€ã³ã¿ãŒãã§ã€ã¹ã䜿çšãããšãåæåããã«è¡åã衚瀺ã§ããŸãã
察å¿ããããã€ã¹ããªãŒãã¡ã€ã«ïŒäŸã¯ã«ãŒãã«ã®ããã¥ã¡ã³ãããååŸïŒïŒ
gpio-line-names = "MMC-CD", "MMC-WP", "VDD eth", "RST eth", "LED R", "LED G", "LED B", "Col A", "Col B", "Col C", "Col D", "Row A", "Row B", "Row C", "Row D", "NMI button", "poweroff", "reset";
é£çµ¡å
ããšã«gpioline_infoæ§é äœã«ååã衚瀺ãããŸãããæ®å¿µãªãããSBCãåºãæ®åããŠããå Žåã§ããé£çµ¡å
ã«ååãä»ãã人ã¯ã»ãšãã©ããŸããã
sysfsã§ã¯å©çšã§ããªãUapiæ©èœ
次ã«ãå€ãã€ã³ã¿ãŒãã§ã€ã¹ã§ã¯å©çšã§ããªãå©ç¹ããªã¹ãããŸãã
ç§ãèããäž»ãªå©ç¹ã¯ãå²ã蟌ã¿ãã³ãã©ãŒã®äžååã§ã€ãã³ãã«å²ãåœãŠãããã¿ã€ã ã¹ã¿ã³ãã§ãã ããã¯ãã€ãã³ãéã®æéãæ£ç¢ºã«æž¬å®ããå¿
èŠãããã¢ããªã±ãŒã·ã§ã³ã«äžå¯æ¬ ã§ãã
le->timestamp = ktime_get_real_ns();
ããã€ã¹ãã©ã€ããŒãèš±å¯ããå Žåãã©ã€ã³ã¯ããã«ãªãŒãã³ã³ã¬ã¯ã¿ãŒïŒ GPIOLINE_FLAG_OPEN_DRAIN ïŒãŸãã¯ãªãŒãã³ãšããã¿ãŒïŒ GPIOLINE_FLAG_OPEN_SOURCE ïŒãšããŠæ§æã§ããŸãããã®ã€ãããŒã·ã§ã³ã¯sysfsã«ç°¡åã«è»¢éã§ããŸãããLinus Werleyãå察ããŠãããããããã¯èµ·ãããŸããã
ãŸããæ°ããapiã䜿çšãããšãåæåäžã«gpiohandle_requestãã£ãŒã«ãconsumer_labelã§åé£çµ¡å
ã«ã«ã¹ã¿ã ã©ãã«ãå²ãåœãŠãããšãã§ããŸãã
çµè«ãšããŠãé£çµ¡å
ã®å·ã®ã°ã«ãŒããããã«ãèªã¿åããããã³ãæžã蟌ã¿ãããããšãã§ããŸãã
çµè«ã®æ¯èŒ
䞻芳çã«ã uapiã¯sysfsãããæ±ãã«ããããã«èŠããŸãããæšæºã®GNUãŠãŒãã£ãªãã£catããã³echoããã³Cã³ãŒããä»ããŠå¶åŸ¡ãæ¯èŒããããšãå¿ããªãã§ãã ãããåã€ã³ã¿ãŒãã§ã€ã¹ã®Cã³ãŒããæ¯èŒãããšãè€éããšããªã¥ãŒã ãã»ãŒåãã§ããããšãããããŸãã
éèŠãªç¹ã¯ã sysfsã䜿çšããå ŽåããŠãŒã¶ãŒãå察ãèŠæ±ãããããªããŒããããŸã§ãè¡ã¯åæåããããŸãŸã«ãªããšããããšã§ãã uapiã¯ããã¡ã€ã«èšè¿°åãéããçŽåŸã«è¡ã解æŸããŸãã
Uapiã®å©ç¹
- syscallãç¯çŽããŸãïŒgpio / valueãèªã¿åã£ãåŸãlseekã®å¿
èŠæ§ãå¿ããªãã§ãã ããïŒã
- å
¥åãŸãã¯åºåã®é
åãåæåããŸãã
- å
¥åãŸãã¯åºåã®é
åã®èªã¿åããŸãã¯æžã蟌ã¿ã
- ãªãŒãã³ãã¬ã€ã³ãšãªãŒãã³ãœãŒã¹
- ã«ã¹ã¿ã ã¿ã°
- ã€ãã³ãã§éä¿¡ãããããªã¢ã«ã¿ã€ã ããç§ã¿ã€ã ã¹ã¿ã³ãã
æ¹è©UAPI
å
¬åŒãŸãã¯éå
¬åŒã®æ¹å€ã¯ãããŸããããŸãã¯ç§ã¯ãããèŠã€ããŸããã§ããã ãããã£ãŠãç§ãã¡èªèº«ã®èããããã€ãç解ããŸãããã
- ããã·ã¥ãã«ããããŠã³ã¹ããã«ã¢ããããã«ããŠã³ããã€ãã¹ããçç±ã¯äžæã§ãã
- struct gpioevent_dataã§ãçŸåšã®è¡ã®å€ã«å€ãã©ã¡ãŒã¿ãŒãè¿œå ãããšäŸ¿å©ã§ã
sysfs gpioã®æ¹å€
sysfsã€ã³ã¿ãŒãã§ãŒã¹ã«å¯Ÿããå
¬åŒã®æ¹å€ã§çµãããŸãããã Linus VaerliïŒã«ãŒãã«å
ã®gpioããã³pinctrlãµãã·ã¹ãã ã«ä»å±ïŒã®ãããã«é¢ããã³ã¡ã³ãã§ã次ã®è«æãææ¡ãããŸããã
- äžåºŠã«è€æ°ã®åç·ããªãã«ããããšã¯äžå¯èœã§ã
- sysfsãæ©èœããããã«ã¯ãã«ãŒãã«æ§æã§å¯Ÿå¿ããããŒãæå¹ã«ããå¿
èŠããããŸã
- gpioã¢ããªã±ãŒã·ã§ã³ãã¯ã©ãã·ã¥ããå Žåãåç·ã¯ãåæåããããç¶æ
ã®ãŸãŸã«ãªããŸã
- å¿
èŠãªè¡ãèŠã€ããã®ãé£ãã
- ãsysfsã¯ã²ã©ãå£ããŠããŸãã©
äžè¬çã«ããããŠæ£çŽã«èšããšãsysfsã¯ãŠãŒã¶ãŒç©ºéã§gpioã«å²ãåœãŠãããã¿ã¹ã¯ã«ãšã£ãŠéåžžã«æ£åžžã ãšæããŸãã é»æ°å·¥åŠã®åºç€ã«è©³ãããªã人ã§ãechoã䜿çšããŠã©ã€ããç¹ç¯ã§ãããšãããã³ããã¯ãªãã®ãçãŸããŸãã æ°ããã€ã³ã¿ãŒãã§ã€ã¹ã§ã¯ã察話ã«è¿œå ã®ãŠãŒãã£ãªãã£ãå¿
èŠã«ãªãããããã®ãããªçŽæ¥æ¥ç¶ã¯æããããŸããã
ããããGPIOã¯ãã°ãã°ã°ã«ãŒããšããŠäžç·ã«äœ¿çšãããŸãã ç°¡åãªäŸïŒãããŠå¯äžïŒãšããŠãI2Cãã¹ãšããŠäœ¿çšãããGPIOã®ãã¢ãèããŸãã 1è¡ã¯ããŒã¿ãåŠçãããã1è¡ã¯ã¯ããã¯ãåŠçããŸãã
æåã®è«æã«ã€ããŠã¯äœãèšããŸããããã®ãããªããŒãºã«åºäŒã£ãããšã¯ãããŸãããæçµçã«ãé£çµ¡å
ãããã«ããã€ã¹ããªãŒã®å
¥åãŸãã¯åºåãšããŠåæåã§ããŸã ã ãã®æ©èœã¯ã ãŠãŒã¶ãŒç©ºéã§ããããã³ã®ã³ã°ãå¿
èŠãªäººã«ãšã£ãŠæçšã§ããããšãç¥ã£ãŠããŸãããããã«ã¯1ã€ãããŸããã çŽç²ãª Linuxã§ã¯ã ããããã³ã®ã³ã°ã¯éåžžã«äœåšæ³¢ã®ãã®ã«ã®ã¿å¯èœã§ãããå°ãªããšãPREEMPT_RTããããå¿
èŠã§ã ã
2çªç®ã®è«æãå¥åŠã§ãsysfsãç¡å¹ã«ããå¿
èŠãããã»ã©ã®ã¹ããŒã¹ç¯çŽã¯æ³åã§ããŸããã
3çªç®ã¯ããã«å¥åŠã§ããã¢ããªã±ãŒã·ã§ã³ããã¯ã©ãã·ã¥ããããå¿
èŠã¯ãªãã®ã§ããããã
4çªç®ã«ã€ããŠã¯ãåºæ¬çã«äœãæ¬è³ªçã«å€ãã£ãŠããªããšèšããã ãã©ãããã©ãŒã ãã©ã€ããŒãŸãã¯gpiochipã®ããã€ã¹ããªãŒã©ãã«ã§æå®ãããŠãããã®ãtrueã®å Žåããæ€çŽ¢ãã¯åçŽã§ããããhell-likeããšåŒã°ããå Žåãã€ã³ã¿ãŒãã§ã€ã¹ã¯ããã§ã¯åœ¹ã«ç«ã¡ãŸããã
äžè¬çã«ãããããããçãã¯èŠã€ãããŸããã§ããã ç§ã¯æ°ããã€ã³ã¿ãŒãã§ãŒã¹ã«å察ããŠããããã§ã¯ãããŸããããããã§ãç§ã¯ããã§ãããå€ãã€ã³ã¿ãŒãã§ãŒã¹ããã®ããã«æ³šææ·±ãæãäžããããšã¯å人çã«ç解ã§ãããäžå¿«ã§ãã
å
¬çäºæ¥
uapiã®å Žåãsysfsã»ã©å€ãã¯ãããŸããã
https://github.com/torvalds/linux/tree/master/tools/gpio
- gpio-event-mon- gpioåç·ã®ã€ãã³ãã远跡ããããã®ãŠãŒãã£ãªãã£
- gpio-hammer-åºå®åšæ³¢æ°ã§nåã©ã€ã³ã®ãªã³/ãªããåãæ¿ããŸã
- lsgpio- gpiochipãšã©ã€ã³ã®ãªã¹ãã®äŸ
libgpiod
https://git.kernel.org/pub/scm/libs/libgpiod/libgpiod.git/
ãã©ã€ããŒgpio - mockupããã³irq-simã®åå¿Bartosz'aGoÅaszewskiã®äœè
ããã
äœæè
ã«ãã£ãŠã©ã€ãã©ãªãšããŠäœçœ®ä»ããããæ°ããuapiã€ã³ã¿ãŒãã§ã€ã¹ãä»ããŠgpioã§ã®äœæ¥ã容æã«ããããã«ãæçšãªãŠãŒãã£ãªãã£ã®ã»ãããå«ãŸããŠããŸãã
- gpiodetect-ååãã©ãã«ãè¡æ°ãå«ãgpiochipãªã¹ã
- gpioinfo-ååããªãã»ãããã©ãã«ãåç·ã¹ããŒã¿ã¹ãå«ãgpiochipãªã¹ã
- gpioget-åç·ã®ç¶æ
ãèªã¿åããŸã
- gpioset-åç·ç¶æ
ãèšå®ããå¿
èŠã«å¿ããŠãæå®ãããæéãä¿¡å·ããŸãã¯ãŠãŒã¶ãŒå
¥åãæéåãã«ãªããŸã§åç·ã䜿çšäžã®ãŸãŸã«ããŸã
- gpiofind-ååã§è¡ãæ€çŽ¢ãã gpiochipNããã€ã¹ãšè¡ãªãã»ããã衚瀺ããŸã
- gpiomonã¯gpio-event-monãšåãã§ã
çŽ æ
- GPIOã€ã³ã¿ãŒãã§ã€ã¹ïŒã¬ã¬ã·ãŒïŒ
- ããã€ã¹ã®GPIOæ
å ±ãæå®ãã
- ã«ãŒãã«ã®ããã€ã¹ã¢ãã«ã®æ°ããå€èŠ³
- ã«ãŒãã«ã®ããã€ã¹ã¢ãã«ã§ããLinus Wã®ã³ã¡ã³ã
- ã·ãã¥ã¬ãŒããããå²ã蟌ã¿
- ã«ãŒãã«v4.6ã®GPIOäžæ¬å€æŽ
åç»
- ãšã³ãžãã¢ããã³ã¡ãŒã«ãŒåãGPIOãLinus Walleij
- ãŠãŒã¶ãŒç©ºéçšã®æ°ããGPIOã€ã³ã¿ãŒãã§ã€ã¹ãBartosz Golaszewski