Created
November 12, 2014 20:06
-
-
Save wendlers/b02c5479c6f647d28a25 to your computer and use it in GitHub Desktop.
Toggle GPIO with IOCTL and Micropython
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
obj-m += pyb_gpio.o | |
ksrc = "$(LINUX_DIR)" | |
sysr = "$(PWD)/../deploy" | |
mdir = "extra" | |
all: | |
make -C $(ksrc) M=$(PWD) modules | |
modules_install: | |
make -C $(ksrc) M=$(PWD) INSTALL_MOD_PATH=$(sysr) INSTALL_MOD_DIR=$(mdir) modules_install | |
clean: | |
make -C $(ksrc) M=$(PWD) clean |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
## | |
# The MIT License (MIT) | |
# | |
# Copyright (c) 2014 Stefan Wendler | |
# | |
# Permission is hereby granted, free of charge, to any person obtaining a copy | |
# of this software and associated documentation files (the "Software"), to deal | |
# in the Software without restriction, including without limitation the rights | |
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
# copies of the Software, and to permit persons to whom the Software is | |
# furnished to do so, subject to the following conditions: | |
# | |
# The above copyright notice and this permission notice shall be included in | |
# all copies or substantial portions of the Software. | |
# | |
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |
# THE SOFTWARE. | |
## | |
""" | |
Simple wrapper to libc open/read/write/seek/ioctl functions using FFI on | |
micropython. | |
""" | |
__author__ = 'Stefan Wendler, [email protected]' | |
import ffi | |
import _libc | |
libc = _libc.get() | |
open = libc.func("i", "open", "si") | |
close = libc.func("i", "close", "i") | |
read = libc.func("i", "read", "isi") | |
write = libc.func("i", "write", "isi") | |
lseek = libc.func("i", "lseek", "iii") | |
ioctl = libc.func("i", "ioctl", "iis") | |
''' | |
Open Flags | |
''' | |
O_ACCMODE = 3 | |
O_RDONLY = 0 | |
O_WRONLY = 1 | |
O_RDWR = 2 | |
O_CREAT = 100 | |
O_EXCL = 200 | |
O_NOCTTY = 400 | |
O_TRUNC = 1000 | |
O_APPEND = 2000 | |
O_NONBLOCK = 4000 | |
O_NDELAY = O_NONBLOCK | |
O_SYNC = 4010000 | |
O_FSYNC = O_SYNC | |
O_ASYNC = 20000 | |
''' | |
Some common error codes | |
''' | |
EPERM = 1 # Operation not permitted | |
ENOENT = 2 # No such file or directory | |
EIO = 5 # I/O error | |
EAGAIN = 11 # Try again | |
ENOMEM = 12 # Out of memory | |
EACCES = 13 # Permission denied | |
EEXIST = 17 # File exists | |
EISDIR = 21 # Is a directory | |
EMFILE = 24 # Too many open files | |
ETXTBSY = 26 # Text file busy | |
EFBIG = 27 # File too large | |
ENOSPC = 28 # No space left on device | |
EROFS= 30 # Read-only file system | |
''' | |
Seek values | |
''' | |
SEEK_SET = 0 | |
SEEK_CUR = 1 | |
SEEK_END = 2 | |
def bytebuffer(size): | |
''' | |
Create a bytebuffer of given size (e.g. for use with read) | |
''' | |
return ('\0' * size) | |
_IOC_NRBITS = 8 | |
_IOC_TYPEBITS = 8 | |
_IOC_SIZEBITS = 14 | |
_IOC_DIRBITS = 2 | |
_IOC_NRMASK = ((1 << _IOC_NRBITS) - 1) | |
_IOC_TYPEMASK = ((1 << _IOC_TYPEBITS) - 1) | |
_IOC_SIZEMASK = ((1 << _IOC_SIZEBITS) - 1) | |
_IOC_DIRMASK = ((1 << _IOC_DIRBITS) - 1) | |
_IOC_NRSHIFT = 0 | |
_IOC_TYPESHIFT = (_IOC_NRSHIFT + _IOC_NRBITS) | |
_IOC_SIZESHIFT = (_IOC_TYPESHIFT + _IOC_TYPEBITS) | |
_IOC_DIRSHIFT = (_IOC_SIZESHIFT + _IOC_SIZEBITS) | |
_IOC_NONE = 0 | |
_IOC_READ = 1 | |
_IOC_WRITE = 2 | |
def _IOC(dir, type, nr, size): | |
return (((dir) << _IOC_DIRSHIFT) | ((type) << _IOC_TYPESHIFT) | ((nr) << _IOC_NRSHIFT) | ((size) << _IOC_SIZESHIFT)) | |
def _IO(type, nr): | |
return _IOC(_IOC_NONE, type, nr, 0) | |
def _IOR(type, nr, size): | |
return _IOC(_IOC_READ, type, nr, size) | |
def _IOW(type, nr, size): | |
return _IOC(_IOC_WRITE, type, nr, size) | |
def _IOWR(type, nr, size): | |
return _IOC(_IOC_READ | _IOC_WRITE, type, nr, size) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Linux Kernel module for simple GPIO access through IOCTL. | |
* | |
* Author: | |
* Stefan Wendler ([email protected]) | |
* | |
* This software is licensed under the terms of the GNU General Public | |
* License version 2, as published by the Free Software Foundation, and | |
* may be copied, distributed, and modified under those terms. | |
* | |
* This program is distributed in the hope that it will be useful, | |
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
* GNU General Public License for more details. | |
* | |
*/ | |
#include <linux/kernel.h> | |
#include <linux/module.h> | |
#include <linux/fs.h> | |
#include <linux/gpio.h> | |
#include <asm/uaccess.h> | |
#define MAJOR_NUM 100 | |
#define IOCTL_GPIO_OUTPUT _IOR(MAJOR_NUM, 0, int) | |
#define IOCTL_GPIO_SET _IOR(MAJOR_NUM, 1, int) | |
#define IOCTL_GPIO_CLEAR _IOR(MAJOR_NUM, 2, int) | |
#define DEVICE_FILE_NAME "/dev/pyb_gpio" | |
#define SUCCESS 0 | |
#define DEVICE_NAME "char_dev" | |
#define BUF_LEN 80 | |
static int is_open = 0; | |
/* | |
* This is called whenever a process attempts to open the device file | |
*/ | |
static int device_open(struct inode *inode, struct file *file) | |
{ | |
if(is_open) | |
return -EBUSY; | |
is_open++; | |
try_module_get(THIS_MODULE); | |
return SUCCESS; | |
} | |
static int device_release(struct inode *inode, struct file *file) | |
{ | |
is_open--; | |
module_put(THIS_MODULE); | |
return SUCCESS; | |
} | |
long device_ioctl(struct file *file, unsigned int ioctl_num, unsigned long ioctl_param) | |
{ | |
switch (ioctl_num) { | |
case IOCTL_GPIO_OUTPUT: | |
gpio_request_one(ioctl_param, GPIOF_DIR_OUT, "pyb_gpio"); | |
break; | |
case IOCTL_GPIO_SET: | |
gpio_set_value(ioctl_param, 1); | |
break; | |
case IOCTL_GPIO_CLEAR: | |
gpio_set_value(ioctl_param, 0); | |
break; | |
} | |
return SUCCESS; | |
} | |
struct file_operations Fops = { | |
.unlocked_ioctl = device_ioctl, | |
.open = device_open, | |
.release = device_release, /* a.k.a. close */ | |
}; | |
static int __init mod_init(void) | |
{ | |
int ret; | |
ret = register_chrdev(MAJOR_NUM, DEVICE_NAME, &Fops); | |
if (ret < 0) | |
{ | |
printk(KERN_ALERT "%s failed with %d\n", | |
"Unable registering character device ", ret); | |
return ret; | |
} | |
printk(KERN_INFO "major device number is %d.\n", MAJOR_NUM); | |
printk(KERN_INFO "create device node with: mknod %s c %d 0\n", DEVICE_FILE_NAME, MAJOR_NUM); | |
return 0; | |
} | |
static void __exit mod_exit(void) | |
{ | |
unregister_chrdev(MAJOR_NUM, DEVICE_NAME); | |
} | |
MODULE_LICENSE("GPL"); | |
MODULE_AUTHOR("Stefan Wendler"); | |
MODULE_DESCRIPTION("GPIO access through IOCTL"); | |
module_init(mod_init); | |
module_exit(mod_exit); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
## | |
# The MIT License (MIT) | |
# | |
# Copyright (c) 2014 Stefan Wendler | |
# | |
# Permission is hereby granted, free of charge, to any person obtaining a copy | |
# of this software and associated documentation files (the "Software"), to deal | |
# in the Software without restriction, including without limitation the rights | |
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
# copies of the Software, and to permit persons to whom the Software is | |
# furnished to do so, subject to the following conditions: | |
# | |
# The above copyright notice and this permission notice shall be included in | |
# all copies or substantial portions of the Software. | |
# | |
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |
# THE SOFTWARE. | |
## | |
""" | |
Toggle GPIO with IOCTL and micropython | |
""" | |
__author__ = 'Stefan Wendler, [email protected]' | |
import sys | |
import nio | |
import time | |
MAJOR_NUM = 100 | |
DEVICE_FILE = '/dev/pyb_gpio' | |
GPIO = 22 | |
''' | |
Calculate IOCTL IDs | |
''' | |
IOCTL_GPIO_OUTPUT = nio._IOR(MAJOR_NUM, 0, 4) | |
IOCTL_GPIO_SET = nio._IOR(MAJOR_NUM, 1, 4) | |
IOCTL_GPIO_CLEAT = nio._IOR(MAJOR_NUM, 2, 4) | |
f = nio.open(DEVICE_FILE, nio.O_RDWR) | |
if f < 0: | |
print("Failed to open device file: %s" % DEVICE_FILE) | |
sys.exit(1) | |
if nio.ioctl(f, IOCTL_GPIO_OUTPUT, GPIO) != 0: | |
print("IOCTL_GPIO_OUTPUT failed") | |
sys.exit(1) | |
try: | |
while True: | |
nio.ioctl(f, IOCTL_GPIO_SET, GPIO) | |
time.sleep(0.25) | |
nio.ioctl(f, IOCTL_GPIO_SET, GPIO) | |
time.sleep(0.25) | |
except KeyboardInterrupt: | |
pass | |
nio.close(f) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment