├── .gitignore ├── ChangeLog ├── LICENCE ├── Makefile.am ├── README.md ├── bindings └── python │ ├── Makefile.am │ ├── __init__.py │ ├── gpio.py │ ├── i2c.py │ ├── libsoc_python.c │ └── spi.py ├── config └── m4 │ └── .gitignore ├── configure.ac ├── contrib └── board_files │ ├── Makefile.am │ ├── apalis-imx6.conf │ ├── apalis-t30.conf │ ├── apalis-tk1.conf │ ├── artik_710.conf │ ├── beaglebone_black.conf │ ├── bubblegum.conf │ ├── chip.conf │ ├── colibri-imx6.conf │ ├── colibri-imx6ull.conf │ ├── colibri-imx6ullwb.conf │ ├── colibri-imx7-1GB.conf │ ├── colibri-imx7-512mb.conf │ ├── colibri-t20.conf │ ├── colibri-t30.conf │ ├── colibri-vf50.conf │ ├── colibri-vf61.conf │ ├── dragonboard410c.conf │ ├── dragonboard820c.conf │ ├── example.conf │ ├── hikey.conf │ ├── odroid_c2.conf │ ├── opos6ul_dev.conf │ ├── pocketbeagle.conf │ ├── raspberrypi3b-rev1v2.conf │ ├── raspberrypi3b-rev1v3.conf │ ├── sd600_eval.conf │ └── tinkerboard_rk3288.conf ├── lib ├── Makefile.am ├── board.c ├── conffile.c ├── debug.c ├── file.c ├── gpio.c ├── i2c.c ├── include │ ├── libsoc_board.h │ ├── libsoc_conffile.h │ ├── libsoc_debug.h │ ├── libsoc_file.h │ ├── libsoc_gpio.h │ ├── libsoc_i2c.h │ ├── libsoc_pwm.h │ └── libsoc_spi.h ├── pwm.c └── spi.c ├── libsoc.pc.in ├── roadmap ├── TODO └── adc ├── static-docs ├── .gitignore ├── README ├── docs │ ├── .gitignore │ ├── c │ │ ├── debug.md │ │ ├── gpio.md │ │ ├── i2c.md │ │ ├── pwm.md │ │ └── spi.md │ ├── index.md │ └── python.md └── mkdocs.yml └── test ├── board_test.c ├── gpio_test.c ├── gpio_test.py ├── i2c_test.c ├── i2c_test.py ├── pwm_test.c ├── spi_test.c ├── spi_test.py └── test_configure.sh /.gitignore: -------------------------------------------------------------------------------- 1 | clean_all.sh 2 | build_all.sh 3 | sync_all.sh 4 | 5 | aclocal.m4 6 | arm-oe-linux-gnueabi-libtool 7 | autom4te.cache/ 8 | bindings/python/gpio.py 9 | compile 10 | config.guess 11 | config.log 12 | config.status 13 | config.sub 14 | config/autoconf 15 | configure 16 | depcomp 17 | install-sh 18 | *.deps/ 19 | *.libs 20 | *Makefile 21 | *Makefile.in 22 | ltmain.sh 23 | missing 24 | test/gpio_test 25 | test/spi_test 26 | test/i2c_test 27 | test/pwm_test 28 | libtool 29 | libsoc.pc 30 | *.la 31 | *.lo 32 | *.o 33 | *.pyc 34 | *.swp 35 | -------------------------------------------------------------------------------- /ChangeLog: -------------------------------------------------------------------------------- 1 | 21/06/2016 - 0.8.2 2 | ------------------ 3 | 4 | - Added set_edge and set_direction to python GPIO bindings 5 | - Started markdown based written documentation 6 | - Build system cleanups 7 | 8 | 05/05/2016 - 0.8.1 9 | ------------------ 10 | 11 | - Fixed some configure bugs relating to installing board files 12 | 13 | 04/05/2016 - 0.8 14 | ---------------- 15 | 16 | - Automatic board probing support via config file 17 | - Python GPIO and I2C bindings 18 | - test_configure.sh test script to catch configure regressions 19 | 20 | - Special Thanks to Andy Doan 21 | 22 | 09/12/2015 - 0.7.1 23 | ------------------ 24 | 25 | - Fixed compilation with musl 26 | - Remove inline keywords as they dont play nice with GCC 5.2 27 | - Misc cleanups from static analysis 28 | 29 | 05/11/2015 - 0.7 30 | ---------------- 31 | 32 | - Add named GPIO board support 33 | - Fixed autoconf syntax error 34 | 35 | - Special Thanks to Andy Doan 36 | 37 | 02/07/2015 - 0.6.5 38 | ---------------- 39 | 40 | - Fix bug in GPIO interrupt polling 41 | 42 | 14/06/2015 - 0.6.4 43 | ---------------- 44 | 45 | - Fix autotools warnings 46 | - Enable silent build 47 | - Add packageconfig support 48 | 49 | - Special Thanks to Yegor Yefremov 50 | 51 | 22/08/2014 - 0.6.3 52 | ---------------- 53 | 54 | - Initialise GPIO function pointer to NULL 55 | - Style fixes 56 | - Small scope optimisations 57 | - Juggling of include files to more relevant places 58 | 59 | - Special Thanks to Yegor Yefremov 60 | 61 | 16/06/2014 - 0.6.2 62 | ---------------- 63 | 64 | - Moved some required headers to include files 65 | - Fix memory leak in GPIO lib error path 66 | - Fix wrong SPI brackets in libsoc_spi_read which caused 67 | function to return FAILURE regardless 68 | 69 | - Special Thanks to Yegor Yefremov 70 | 71 | 22/05/2014 - 0.6.1 72 | -------------- 73 | 74 | - Add support for BOTH edge interrupts 75 | - Add include guards 76 | - Add C++ ifdef support 77 | - Include sysfs gpio bug fix for OMAP platforms 78 | 79 | 02/02/2014 - 0.6 80 | ------------ 81 | 82 | - PWM sysfs support (Linux 3.12+) 83 | - Fixed some bugs 84 | - Enabled debugging by default; you will now have to specifically 85 | switch it off (./configure --disable-debug) 86 | 87 | 06/12/2013 - 0.5 88 | ---------------------- 89 | 90 | - Basic I2C support 91 | - Add SPI header to include_header in configure.ac 92 | 93 | 06/10/2013 - 0.4 94 | -------------- 95 | 96 | - Basic SPI support 97 | - See lib/include/libsoc_spi.h 98 | 99 | 13/09/2013 - 0.3 100 | -------------- 101 | 102 | - Non-blocking GPIO interrupts 103 | 104 | /** 105 | * \fn int libsoc_gpio_callback_interrupt(gpio* gpio, int (*callback_fn)(void*), void* arg) 106 | * \brief takes a gpio and a callback function, when an interrupt occurs 107 | * on the edge previously specified, the callback function is called 108 | * \param gpio* gpio - the gpio for which you want the interrupt to 109 | * trigger the callback function 110 | * \param int (*callback_fn)(void*) - the function you wish to call with 111 | * a void* pointer to a possible value you may wish to use in the callback. 112 | * \param void* arg - pointer to data you wish to use in the callback function 113 | * \return EXIT_SUCCESS or EXIT_FAILURE 114 | */ 115 | 116 | int libsoc_gpio_callback_interrupt(gpio* gpio, int (*callback_fn)(void*), void* arg); 117 | 118 | /** 119 | * \fn int libsoc_gpio_callback_interrupt_cancel(gpio* gpio) 120 | * \brief cancel a callback on a gpio interrupt 121 | * \param gpio* gpio - gpio with a valid callback enabled 122 | * \return EXIT_SUCCESS or EXIT_FAILURE 123 | */ 124 | 125 | int libsoc_gpio_callback_interrupt_cancel(gpio* gpio); 126 | 127 | - Added modes to gpio_request 128 | 129 | gpio* libsoc_gpio_request(unsigned int gpio_id, int mode); 130 | 131 | /** 132 | * Valid Modes for libsoc_gpio_request 133 | * 134 | * LS_SHARED - if the gpio is already exported then it will not unexport 135 | * the GPIO on free. If it is not exported, then it will 136 | * unexport on free. 137 | * 138 | * LS_GREEDY - will succeed if the GPIO is already exported, but will 139 | * always unexport the GPIO on free. 140 | * 141 | * LS_WEAK - will fail if GPIO is already exported, will always unexport 142 | * on free. 143 | */ 144 | 145 | 03/09/2013 - 0.2 146 | -------------- 147 | 148 | - GPIO blocking interrupt support 149 | 150 | /** 151 | * \fn int libsoc_gpio_wait_interrupt(gpio* gpio, int timeout) 152 | * \brief takes a gpio and waits for length of timeout or until an 153 | * interrupt occurs. Will return EXIT_SUCCESS on interrupt or 154 | * EXIT_FAILURE on error or timeout. 155 | * \param gpio* gpio - the gpio for which you want to wait on interrupt 156 | * \param int timeout - the max length of time to wait for interrupt in 157 | * milliseconds 158 | * \return EXIT_SUCCESS on interrupt caught, EXIT_FAILURE on error or 159 | * interrupt missed 160 | */ 161 | 162 | int libsoc_gpio_wait_interrupt(gpio* gpio, int timeout); 163 | 164 | - Improved error and debug handling 165 | 166 | 31/08/2013 - 0.1 167 | -------------- 168 | 169 | - basic sysfs GPIO support 170 | -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 1 | ACLOCAL_AMFLAGS = -I config/m4 2 | AUTOMAKE_OPTIONS = subdir-objects 3 | 4 | pkgconfigdir = $(libdir)/pkgconfig 5 | pkgconfig_DATA = libsoc.pc 6 | EXTRA_DIST = libsoc.pc.in 7 | CLEANFILES = libsoc.pc 8 | 9 | SUBDIRS=lib contrib/board_files 10 | 11 | if HAVE_PYTHON 12 | SUBDIRS += bindings/python 13 | endif 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | static-docs/docs/index.md -------------------------------------------------------------------------------- /bindings/python/Makefile.am: -------------------------------------------------------------------------------- 1 | libsocdir = $(pyexecdir)/libsoc 2 | libsoc_PYTHON = __init__.py gpio.py i2c.py spi.py 3 | 4 | AM_CPPFLAGS = $(PYTHON_CFLAGS) -I${top_srcdir}/lib/include -DLIBSOC_SO=\"libsoc.so.2\" 5 | 6 | libsoc_LTLIBRARIES = _libsoc.la 7 | _libsoc_la_LDFLAGS = -module -avoid-version -export-dynamic $(PYTHON_LIBS) 8 | _libsoc_la_SOURCES = libsoc_python.c 9 | -------------------------------------------------------------------------------- /bindings/python/__init__.py: -------------------------------------------------------------------------------- 1 | from ._libsoc import * # NOQA 2 | from .gpio import * # NOQA 3 | from .i2c import * # NOQA 4 | from .spi import * # NOQA 5 | -------------------------------------------------------------------------------- /bindings/python/gpio.py: -------------------------------------------------------------------------------- 1 | import atexit 2 | import contextlib 3 | import threading 4 | import time 5 | 6 | from ._libsoc import ( 7 | DIRECTION_INPUT, DIRECTION_OUTPUT, 8 | EDGE_BOTH, EDGE_FALLING, EDGE_NONE, EDGE_RISING, 9 | LS_GPIO_SHARED, LS_GPIO_GREEDY, LS_GPIO_WEAK, api 10 | ) 11 | 12 | 13 | class InterruptHandler(threading.Thread): 14 | def __init__(self, gpio, interrupt_callback): 15 | super(InterruptHandler, self).__init__() 16 | self.gpio = gpio 17 | self.isr_cb = interrupt_callback 18 | self.running = False 19 | 20 | def run(self): 21 | self.running = True 22 | while self.running: 23 | if self.gpio.poll(1000): 24 | self.isr_cb() 25 | 26 | def stop(self): 27 | self.running = False 28 | 29 | 30 | class GPIO(object): 31 | _board_config = None 32 | 33 | def __init__(self, id, direction, edge=EDGE_NONE, mode=LS_GPIO_SHARED): 34 | self.id = id 35 | if not isinstance(id, int): 36 | raise TypeError('Invalid gpio id must be an "int"') 37 | if mode not in (LS_GPIO_SHARED, LS_GPIO_GREEDY, LS_GPIO_WEAK): 38 | raise ValueError('Invalid GPIO mode: %d' % mode) 39 | self._validate_direction(direction, edge) 40 | self.mode = mode 41 | self._gpio = None 42 | 43 | def _validate_direction(self, direction, edge=EDGE_NONE): 44 | if direction not in (DIRECTION_INPUT, DIRECTION_OUTPUT): 45 | raise ValueError('Invalid GPIO direction: %d' % direction) 46 | edges = (EDGE_RISING, EDGE_FALLING, EDGE_NONE, EDGE_BOTH) 47 | if direction == DIRECTION_INPUT and edge not in edges: 48 | raise ValueError('Invalid GPIO edge: %d' % edge) 49 | self.direction = direction 50 | self.edge = edge 51 | 52 | def open(self): 53 | '''Opens a file descriptor to the GPIO and configures it.''' 54 | assert self._gpio is None 55 | self._gpio = api.libsoc_gpio_request(self.id, self.mode) 56 | if self._gpio == 0: # NULL from native code 57 | raise IOError('Unable to open GPIO_%d' % self.id) 58 | self.set_direction(self.direction, self.edge) 59 | 60 | def close(self): 61 | '''Cleans up the memory and resources allocated by the open method.''' 62 | if self._gpio: 63 | api.libsoc_gpio_free(self._gpio) 64 | self._gpio = None 65 | 66 | def set_direction(self, direction, edge): 67 | self._validate_direction(direction, edge) 68 | api.libsoc_gpio_set_direction(self._gpio, self.direction) 69 | if self.direction == DIRECTION_INPUT: 70 | if api.libsoc_gpio_set_edge(self._gpio, self.edge) != 0: 71 | raise IOError('Error setting edge for GPIO_%d' % self.id) 72 | 73 | def set_edge(self, edge): 74 | self._validate_direction(self.direction, edge) 75 | if api.libsoc_gpio_set_edge(self._gpio, self.edge) != 0: 76 | raise IOError('Error setting edge for GPIO_%d' % self.id) 77 | 78 | def get_direction(self): 79 | d = api.libsoc_gpio_get_direction(self._gpio) 80 | if d == -1: 81 | raise IOError('Error reading GPIO_%d direction: %d' % self.id) 82 | return d 83 | 84 | @staticmethod 85 | def gpio_id(pin): 86 | '''Given a pin number on the board, return the actual GPIO ID.''' 87 | if not GPIO._board_config: 88 | GPIO._board_config = api.libsoc_board_init() 89 | atexit.register(api.libsoc_board_free, GPIO._board_config) 90 | gpio = api.libsoc_board_gpio_id(GPIO._board_config, pin.encode()) 91 | if gpio == -1: 92 | raise ValueError('Invalid GPIO pin name(%s)' % pin) 93 | return gpio 94 | 95 | @staticmethod 96 | def set_debug(enabled): 97 | v = 0 98 | if enabled: 99 | v = 1 100 | api.libsoc_set_debug(v) 101 | 102 | def set_high(self): 103 | assert self.direction == DIRECTION_OUTPUT 104 | api.libsoc_gpio_set_level(self._gpio, 1) 105 | 106 | def set_low(self): 107 | assert self.direction == DIRECTION_OUTPUT 108 | api.libsoc_gpio_set_level(self._gpio, 0) 109 | 110 | def is_high(self): 111 | l = api.libsoc_gpio_get_level(self._gpio) 112 | if l == -1: 113 | raise IOError('Error reading GPIO_%d level' % self.id) 114 | return l == 1 115 | 116 | def wait_for_interrupt(self, timeout): 117 | assert self.direction == DIRECTION_INPUT 118 | if api.libsoc_gpio_wait_interrupt(self._gpio, timeout) != 0: 119 | raise IOError('Error waiting for interrupt on GPIO_%d' % self.id) 120 | 121 | def get_edge(self): 122 | '''Return the edge the GPIO is configured with.''' 123 | assert self.direction == DIRECTION_INPUT 124 | e = api.libsoc_gpio_get_edge(self._gpio) 125 | if e == -1: 126 | raise IOError('Error reading GPIO_%d edge' % self.id) 127 | return e 128 | 129 | def poll(self, timeout_ms=-1): 130 | '''Nearly the same as wait_for_interrupt, but with less overhead. 131 | wait_for_interrupt does some sanity checks of the GPIO settings before 132 | polling. Returns True if an interrupt occurred, False on an error or 133 | timeout 134 | ''' 135 | return api.libsoc_gpio_poll(self._gpio, timeout_ms) == 0 136 | 137 | def start_interrupt_handler(self, interrupt_callback): 138 | '''Returns a thread that continuosly polls the GPIO. If an interrupt is 139 | encountered, the interrupt_callback function will be run. This 140 | thread can be stopped by calling interrupt_handler.stop() 141 | ''' 142 | ih = InterruptHandler(self, interrupt_callback) 143 | ih.start() 144 | while not ih.running: 145 | time.sleep(0.01) 146 | return ih 147 | 148 | 149 | @contextlib.contextmanager 150 | def request_gpios(gpios): 151 | if not isinstance(gpios, tuple) and not isinstance(gpios, list): 152 | gpios = (gpios,) 153 | try: 154 | for g in gpios: 155 | g.open() 156 | yield 157 | finally: 158 | for g in reversed(gpios): 159 | g.close() 160 | -------------------------------------------------------------------------------- /bindings/python/i2c.py: -------------------------------------------------------------------------------- 1 | import sys 2 | from ctypes import create_string_buffer 3 | 4 | from ._libsoc import api 5 | 6 | PY3 = sys.version_info >= (3, 0) 7 | 8 | 9 | class I2C(object): 10 | def __init__(self, bus, address): 11 | if not isinstance(bus, int): 12 | raise TypeError('Invalid bus id must be an "int"') 13 | if not isinstance(address, int): 14 | raise TypeError('Invalid bus address must be an "int"') 15 | self.bus = bus 16 | self.addr = address 17 | self._i2c = None 18 | 19 | def __enter__(self): 20 | self.open() 21 | return self 22 | 23 | def __exit__(self, type, value, traceback): 24 | self.close() 25 | 26 | def open(self): 27 | '''Opens a file descriptor to the GPIO and configures it.''' 28 | assert self._i2c is None 29 | self._i2c = api.libsoc_i2c_init(self.bus, self.addr) 30 | if self._i2c == 0: # NULL from native code 31 | raise IOError( 32 | 'Unable to open i2c bus(%d) addr(%d)' % (self.bus, self.addr)) 33 | 34 | def close(self): 35 | '''Cleans up the memory and resources allocated by the open method.''' 36 | if self._i2c: 37 | api.libsoc_i2c_free(self._i2c) 38 | self._i2c = None 39 | 40 | @staticmethod 41 | def set_debug(enabled): 42 | v = 0 43 | if enabled: 44 | v = 1 45 | api.libsoc_set_debug(v) 46 | 47 | def set_timeout(self, timeout): 48 | if not isinstance(timeout, int): 49 | raise TypeError('Invalid timeout must be an "int"') 50 | api.libsoc_i2c_set_timeout(self._i2c, timeout) 51 | 52 | def read(self, num_bytes): 53 | buff = create_string_buffer(num_bytes) 54 | if api.libsoc_i2c_read(self._i2c, buff, num_bytes) == -1: 55 | raise IOError('Error reading i2c device') 56 | return buff.value 57 | 58 | def write(self, byte_array): 59 | if PY3: 60 | buff = bytes(byte_array) 61 | else: 62 | buff = ''.join(map(chr, byte_array)) 63 | api.libsoc_i2c_write(self._i2c, buff, len(buff)) 64 | -------------------------------------------------------------------------------- /bindings/python/libsoc_python.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "libsoc_gpio.h" 4 | #include "libsoc_spi.h" 5 | 6 | static PyMethodDef functions[] = { 7 | {NULL, NULL, 0, NULL} /* Sentinel */ 8 | }; 9 | 10 | static void 11 | _add_constants(PyObject *m) 12 | { 13 | PyObject *mod, *func, *args, *api; 14 | 15 | PyModule_AddIntConstant(m, "DIRECTION_ERROR", DIRECTION_ERROR); 16 | PyModule_AddIntConstant(m, "DIRECTION_INPUT", INPUT); 17 | PyModule_AddIntConstant(m, "DIRECTION_OUTPUT", OUTPUT); 18 | 19 | PyModule_AddIntConstant(m, "LEVEL_ERROR", LEVEL_ERROR); 20 | PyModule_AddIntConstant(m, "LEVEL_LOW", LOW); 21 | PyModule_AddIntConstant(m, "LEVEL_HIGH", HIGH); 22 | 23 | PyModule_AddIntConstant(m, "EDGE_ERROR", EDGE_ERROR); 24 | PyModule_AddIntConstant(m, "EDGE_RISING", RISING); 25 | PyModule_AddIntConstant(m, "EDGE_FALLING", FALLING); 26 | PyModule_AddIntConstant(m, "EDGE_NONE", NONE); 27 | PyModule_AddIntConstant(m, "EDGE_BOTH", BOTH); 28 | 29 | PyModule_AddIntConstant(m, "LS_GPIO_SHARED", LS_GPIO_SHARED); 30 | PyModule_AddIntConstant(m, "LS_GPIO_GREEDY", LS_GPIO_GREEDY); 31 | PyModule_AddIntConstant(m, "LS_GPIO_WEAK", LS_GPIO_WEAK); 32 | 33 | PyModule_AddIntConstant(m, "BITS_8", BITS_8); 34 | PyModule_AddIntConstant(m, "BITS_16", BITS_16); 35 | PyModule_AddIntConstant(m, "BPW_ERROR", BPW_ERROR); 36 | 37 | PyModule_AddIntConstant(m, "MODE_0", MODE_0); 38 | PyModule_AddIntConstant(m, "MODE_1", MODE_1); 39 | PyModule_AddIntConstant(m, "MODE_2", MODE_2); 40 | PyModule_AddIntConstant(m, "MODE_3", MODE_3); 41 | PyModule_AddIntConstant(m, "MODE_ERROR", MODE_ERROR); 42 | 43 | mod = PyImport_ImportModule("ctypes"); 44 | if (mod == NULL) { 45 | printf("ERROR importing 'ctypes' module:\n"); 46 | PyErr_Print(); 47 | exit(-1); 48 | } 49 | func = PyObject_GetAttrString(mod, "CDLL"); 50 | if (func == NULL) { 51 | printf("ERROR getting 'CDLL' function:\n"); 52 | PyErr_Print(); 53 | exit(-1); 54 | } 55 | if (!PyCallable_Check(func)) { 56 | printf("'CDLL' function is not callable:\n"); 57 | PyErr_Print(); 58 | exit(-1); 59 | } 60 | 61 | args = Py_BuildValue("(s)", LIBSOC_SO); 62 | api = PyObject_CallObject(func, args); 63 | if (api == NULL) { 64 | printf("'CDLL' function call to load '%s' failed:\n", LIBSOC_SO); 65 | PyErr_Print(); 66 | exit(-1); 67 | } 68 | Py_DECREF(args); 69 | PyModule_AddObject(m, "api", api); 70 | } 71 | 72 | 73 | #if PY_MAJOR_VERSION >= 3 74 | static struct PyModuleDef moduledef = { 75 | PyModuleDef_HEAD_INIT, 76 | "_libsoc", 77 | NULL, 78 | -1, 79 | functions, 80 | NULL, 81 | NULL, 82 | NULL, 83 | NULL 84 | }; 85 | 86 | PyMODINIT_FUNC 87 | PyInit__libsoc(void) { 88 | PyObject *m; 89 | m = PyModule_Create(&moduledef); 90 | if (!m) 91 | return NULL; 92 | _add_constants(m); 93 | return m; 94 | } 95 | #else 96 | PyMODINIT_FUNC 97 | init_libsoc(void) 98 | { 99 | PyObject *m; 100 | m = Py_InitModule ("_libsoc", functions); 101 | _add_constants(m); 102 | } 103 | #endif 104 | -------------------------------------------------------------------------------- /bindings/python/spi.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | from ctypes import create_string_buffer 4 | 5 | from ._libsoc import ( 6 | BITS_8, BITS_16, BPW_ERROR, 7 | MODE_0, MODE_1, MODE_2, MODE_3, MODE_ERROR, api 8 | ) 9 | 10 | PY3 = sys.version_info >= (3, 0) 11 | 12 | 13 | class SPI(object): 14 | def __init__(self, spidev_device, chip_select, mode, speed, bpw): 15 | if not isinstance(spidev_device, int): 16 | raise TypeError('Invalid spi device id must be an "int"') 17 | if not isinstance(chip_select, int): 18 | raise TypeError('Invalid spi chip select must be an "int"') 19 | if mode not in (MODE_0, MODE_1, MODE_2, MODE_3): 20 | raise ValueError('Invalid mode: %d' % mode) 21 | if not isinstance(speed, int): 22 | raise TypeError('Invalid speed must be an "int"') 23 | if bpw not in (BITS_8, BITS_16): 24 | raise ValueError('Invalid bits per word: %d' % bpw) 25 | self.device = spidev_device 26 | self.chip = chip_select 27 | self.mode = mode 28 | self.speed = speed 29 | self.bpw = bpw 30 | self._spi = None 31 | 32 | def __enter__(self): 33 | self.open() 34 | return self 35 | 36 | def __exit__(self, type, value, traceback): 37 | self.close() 38 | 39 | def open(self): 40 | assert self._spi is None 41 | self._spi = api.libsoc_spi_init(self.device, self.chip) 42 | if self._spi == 0: 43 | raise IOError('Unable to open spi device(%d)' % self.device) 44 | self.set_mode(self.mode) 45 | if self.get_mode() != self.mode: 46 | raise IOError('Set mode incorrectly') 47 | self.set_speed(self.speed) 48 | if self.get_speed() != self.speed: 49 | raise IOError('Set speed incorrectly') 50 | self.set_bits_per_word(self.bpw) 51 | if self.get_bits_per_word() != self.bpw: 52 | raise IOError('Set bits per word incorrectly') 53 | 54 | def close(self): 55 | if self._spi: 56 | api.libsoc_spi_free(self._spi) 57 | self._spi = None 58 | 59 | @staticmethod 60 | def set_debug(enabled): 61 | v = 0 62 | if enabled: 63 | v = 1 64 | api.libsoc_set_debug(v) 65 | 66 | def set_bits_per_word(self, bpw): 67 | if bpw not in (BITS_8, BITS_16): 68 | raise ValueError('Invalid bits per word: %d' % bpw) 69 | self.bpw = bpw 70 | api.libsoc_spi_set_bits_per_word(self._spi, self.bpw) 71 | 72 | def get_bits_per_word(self): 73 | b = api.libsoc_spi_get_bits_per_word(self._spi) 74 | if b == BPW_ERROR: 75 | raise IOError('bits per word not recognized') 76 | return b 77 | 78 | def set_mode(self, mode): 79 | assert self._spi is not None 80 | if mode not in (MODE_0, MODE_1, MODE_2, MODE_3): 81 | raise ValueError('Invalid mode: %d' % mode) 82 | self.mode = mode 83 | api.libsoc_spi_set_mode(self._spi, self.mode) 84 | 85 | def get_mode(self): 86 | m = api.libsoc_spi_get_mode(self._spi) 87 | if m == MODE_ERROR: 88 | raise IOError('mode not recognized') 89 | return m 90 | 91 | def set_speed(self, speed): 92 | if not isinstance(speed, int): 93 | raise TypeError('Invalid speed must be an "int"') 94 | self.speed = speed 95 | api.libsoc_spi_set_speed(self._spi, self.speed) 96 | 97 | def get_speed(self): 98 | s = api.libsoc_spi_get_speed(self._spi) 99 | if s == -1: 100 | raise IOError('failed reading speed') 101 | return s 102 | 103 | def read(self, num_bytes): 104 | assert num_bytes > 0 105 | buff = create_string_buffer(num_bytes) 106 | if api.libsoc_spi_read(self._spi, buff, num_bytes) == -1: 107 | raise IOError('Error reading spi device') 108 | return buff.raw 109 | 110 | def write(self, byte_array): 111 | assert len(byte_array) > 0 112 | if PY3: 113 | buff = bytes(byte_array) 114 | else: 115 | buff = ''.join(map(chr, byte_array)) 116 | api.libsoc_spi_write(self._spi, buff, len(buff)) 117 | 118 | def rw(self, num_bytes, byte_array): 119 | assert num_bytes > 0 120 | assert len(byte_array) > 0 121 | rbuff = create_string_buffer(num_bytes) 122 | if PY3: 123 | wbuff = bytes(byte_array) 124 | else: 125 | wbuff = ''.join(map(chr, byte_array)) 126 | if api.libsoc_spi_rw(self._spi, wbuff, rbuff, num_bytes) != 0: 127 | raise IOError('Error rw spi device') 128 | return rbuff.raw 129 | -------------------------------------------------------------------------------- /config/m4/.gitignore: -------------------------------------------------------------------------------- 1 | *.m4 2 | -------------------------------------------------------------------------------- /configure.ac: -------------------------------------------------------------------------------- 1 | AC_INIT([libsoc], [0.8.2]) 2 | 3 | AC_CONFIG_SRCDIR([lib/gpio.c]) 4 | AC_CONFIG_MACRO_DIR([config/m4]) 5 | AC_CONFIG_AUX_DIR([config/autoconf]) 6 | 7 | AC_CANONICAL_SYSTEM 8 | AC_PROG_CC 9 | AM_INIT_AUTOMAKE([foreign]) 10 | AM_PROG_CC_C_O 11 | 12 | LT_INIT 13 | 14 | AC_SEARCH_LIBS([pthread_create, pthread_cancel],[pthread], , AC_MSG_WARN(["ERROR: Could not find pthread library"])) 15 | 16 | AC_ARG_ENABLE([debug], 17 | AS_HELP_STRING([--enable-debug], [Enable the debug code])) 18 | 19 | AS_IF([test "x$enable_debug" != "xno"], [ 20 | AC_DEFINE([DEBUG]) 21 | ]) 22 | 23 | AC_ARG_WITH([board-configs], 24 | AS_HELP_STRING([--with-board-configs], [Install all board config files])) 25 | AM_CONDITIONAL([BOARD_CONFIGS], [test "x$with_board_configs" = xyes]) 26 | 27 | AC_ARG_ENABLE([python], 28 | AS_HELP_STRING([--enable-python=PYTHON_VERSION], 29 | [Enable Python language bindings to libsoc API. PYTHON_VERSION can be empty for autodetect, the value 2 or 3 to search 30 | the PATH environment variable for python2 or python3, or an absolute path to a python binary]), 31 | [python_arg=$enable_python], [python_arg="no"]) 32 | 33 | AS_IF([test "x$python_arg" != xno], [ 34 | 35 | AS_CASE(["$python_arg"], 36 | [2|3], [ 37 | PYTHON="python$python_arg" 38 | ], 39 | [yes], [], 40 | [PYTHON="$python_arg"] 41 | ) 42 | 43 | AM_PATH_PYTHON() 44 | 45 | if ! which "$PYTHON"; then 46 | AC_MSG_ERROR([Python interpreter $PYTHON does not exist]) 47 | fi 48 | 49 | PKG_CHECK_MODULES([PYTHON], [python-"$PYTHON_VERSION"]) 50 | ]) 51 | 52 | AM_CONDITIONAL([HAVE_PYTHON], [test "x$PYTHON" != x]) 53 | 54 | AC_ARG_ENABLE([board], 55 | AS_HELP_STRING([--enable-board=BOARD], [Enable installation of board config])) 56 | 57 | AS_IF([test "x$enable_board" != "x"], [ 58 | valid_boards=`ls $srcdir/contrib/board_files/ | grep .conf | tr '\n' ' ' | sed -e 's/.conf//g' -e 's/example//'` 59 | for x in $valid_boards ; do 60 | test "$x" = "$enable_board" && found=1 61 | done 62 | test -z "$found" && AC_MSG_ERROR([Invalid board name: $enable_board, must be one of: $valid_boards]) 63 | ]) 64 | 65 | AC_SUBST([board], $enable_board) 66 | AM_CONDITIONAL([BOARD], [test "x$enable_board" != x]) 67 | 68 | m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) 69 | 70 | AC_CONFIG_FILES(Makefile lib/Makefile contrib/board_files/Makefile bindings/python/Makefile libsoc.pc) 71 | AC_OUTPUT 72 | -------------------------------------------------------------------------------- /contrib/board_files/Makefile.am: -------------------------------------------------------------------------------- 1 | if BOARD_CONFIGS 2 | 3 | BOARD_FILES = $(filter-out example.conf, $(wildcard $(srcdir)/*.conf)) 4 | 5 | libsocdir = $(pkgdatadir) 6 | libsoc_DATA = $(BOARD_FILES) 7 | 8 | if BOARD 9 | installdirs-local: 10 | install -d $(DESTDIR)$(sysconfdir) 11 | 12 | install-data-hook: installdirs-local 13 | ln -srf $(DESTDIR)$(pkgdatadir)/@board@.conf $(DESTDIR)$(sysconfdir)/libsoc.conf 14 | endif 15 | 16 | uninstall-local: 17 | -rmdir $(DESTDIR)$(pkgdatadir) 18 | -rm $(DESTDIR)$(sysconfdir)/libsoc.conf 19 | -rmdir $(DESTDIR)$(sysconfdir) 20 | else 21 | if BOARD 22 | 23 | install-data-hook: 24 | install -D $(srcdir)/@board@.conf $(DESTDIR)$(sysconfdir)/libsoc.conf 25 | 26 | uninstall-local: 27 | -rm $(DESTDIR)$(sysconfdir)/libsoc.conf 28 | -rmdir $(DESTDIR)$(sysconfdir) 29 | 30 | endif 31 | endif 32 | -------------------------------------------------------------------------------- /contrib/board_files/apalis-imx6.conf: -------------------------------------------------------------------------------- 1 | # Toradex Apalis iMX6 Computer On Module. 2 | # http://developer.toradex.com/products/apalis-imx6 3 | 4 | [board] 5 | dtfile = /proc/device-tree/model 6 | model = Toradex Apalis iMX6 on Apalis Evaluation Board 7 | 8 | [GPIO] 9 | ###Apalis IMX6 SODIMM number to GPIO number mapping 10 | 11 | MXM3_1 = 36 12 | MXM3_2 = 9 13 | MXM3_3 = 37 14 | MXM3_4 = 1 15 | MXM3_5 = 38 16 | MXM3_6 = 41 17 | MXM3_7 = 39 18 | MXM3_8 = 42 19 | MXM3_11 = 170 20 | MXM3_12 = 8 21 | MXM3_13 = 169 22 | MXM3_14 = 7 23 | MXM3_15 = 2 24 | MXM3_16 = 111 25 | MXM3_17 = 6 26 | MXM3_18 = 110 27 | MXM3_35 = 79 28 | MXM3_37 = 4 29 | MXM3_72 = 24 30 | MXM3_77 = 148 31 | MXM3_79 = 171 32 | MXM3_83 = 167 33 | MXM3_84 = 0 34 | MXM3_85 = 202 35 | MXM3_89 = 176 36 | MXM3_91 = 168 37 | MXM3_95 = 40 38 | MXM3_96 = 3 39 | MXM3_99 = 201 40 | MXM3_110 = 88 41 | MXM3_112 = 157 42 | MXM3_114 = 84 43 | MXM3_116 = 83 44 | MXM3_118 = 156 45 | MXM3_120 = 89 46 | MXM3_122 = 63 47 | MXM3_123 = 43 48 | MXM3_124 = 87 49 | MXM3_126 = 44 50 | MXM3_128 = 45 51 | MXM3_130 = 46 52 | MXM3_132 = 47 53 | MXM3_134 = 103 54 | MXM3_135 = 93 55 | MXM3_136 = 102 56 | MXM3_138 = 105 57 | MXM3_140 = 104 58 | MXM3_144 = 19 59 | MXM3_146 = 21 60 | MXM3_148 = 32 61 | MXM3_150 = 18 62 | MXM3_152 = 33 63 | MXM3_154 = 20 64 | MXM3_156 = 34 65 | MXM3_158 = 35 66 | MXM3_159 = 128 67 | MXM3_160 = 16 68 | MXM3_162 = 17 69 | MXM3_164 = 116 70 | MXM3_173 = 165 71 | MXM3_175 = 164 72 | MXM3_176 = 13 73 | MXM3_177 = 163 74 | MXM3_178 = 12 75 | MXM3_179 = 162 76 | MXM3_180 = 11 77 | MXM3_181 = 161 78 | MXM3_183 = 160 79 | MXM3_184 = 10 80 | MXM3_185 = 159 81 | MXM3_186 = 15 82 | MXM3_187 = 158 83 | MXM3_188 = 14 84 | MXM3_190 = 174 85 | MXM3_191 = 146 86 | MXM3_193 = 175 87 | MXM3_194 = 101 88 | MXM3_195 = 149 89 | MXM3_196 = 139 90 | MXM3_197 = 147 91 | MXM3_198 = 59 92 | MXM3_200 = 138 93 | MXM3_201 = 82 94 | MXM3_202 = 141 95 | MXM3_203 = 81 96 | MXM3_204 = 140 97 | MXM3_205 = 80 98 | MXM3_207 = 62 99 | MXM3_209 = 154 100 | MXM3_211 = 155 101 | MXM3_214 = 114 102 | MXM3_215 = 204 103 | MXM3_216 = 115 104 | MXM3_217 = 203 105 | MXM3_220 = 107 106 | MXM3_221 = 150 107 | MXM3_223 = 152 108 | MXM3_225 = 151 109 | MXM3_227 = 153 110 | MXM3_229 = 57 111 | MXM3_231 = 56 112 | MXM3_233 = 58 113 | MXM3_235 = 55 114 | MXM3_239 = 78 115 | MXM3_243 = 54 116 | MXM3_245 = 76 117 | MXM3_247 = 75 118 | MXM3_249 = 74 119 | MXM3_251 = 49 120 | MXM3_253 = 48 121 | MXM3_255 = 166 122 | MXM3_257 = 132 123 | MXM3_259 = 95 124 | MXM3_261 = 94 125 | MXM3_262 = 85 126 | MXM3_263 = 90 127 | MXM3_265 = 91 128 | MXM3_269 = 65 129 | MXM3_271 = 64 130 | MXM3_273 = 61 131 | MXM3_274 = 86 132 | MXM3_275 = 60 133 | MXM3_277 = 53 134 | MXM3_279 = 52 135 | MXM3_281 = 51 136 | MXM3_283 = 50 137 | MXM3_286 = 77 138 | MXM3_287 = 73 139 | MXM3_289 = 72 140 | MXM3_291 = 71 141 | MXM3_293 = 70 142 | MXM3_295 = 69 143 | MXM3_297 = 68 144 | MXM3_299 = 67 145 | MXM3_301 = 66 146 | -------------------------------------------------------------------------------- /contrib/board_files/apalis-t30.conf: -------------------------------------------------------------------------------- 1 | # Toradex Apalis T30 Computer On Module. 2 | # http://developer.toradex.com/products/apalis-t30 3 | 4 | [board] 5 | dtfile = /proc/device-tree/model 6 | model = Toradex Apalis T30 on Apalis Evaluation Board 7 | 8 | [GPIO] 9 | ###Apalis T30 SODIMM number to GPIO number mapping 10 | 11 | MXM3_1 = 146 12 | MXM3_2 = 166 13 | MXM3_3 = 147 14 | MXM3_4 = 165 15 | MXM3_5 = 148 16 | MXM3_6 = 164 17 | MXM3_7 = 149 18 | MXM3_8 = 163 19 | MXM3_11 = 150 20 | MXM3_13 = 128 21 | MXM3_15 = 151 22 | MXM3_17 = 129 23 | MXM3_26 = 68 24 | MXM3_35 = 232 25 | MXM3_37 = 169 26 | MXM3_63 = 65 27 | MXM3_84 = 233 28 | MXM3_87 = 135 29 | MXM3_96 = 234 30 | MXM3_99 = 133 31 | MXM3_110 = 112 32 | MXM3_112 = 113 33 | MXM3_114 = 116 34 | MXM3_116 = 115 35 | MXM3_118 = 114 36 | MXM3_120 = 119 37 | MXM3_122 = 117 38 | MXM3_123 = 134 39 | MXM3_124 = 118 40 | MXM3_126 = 192 41 | MXM3_128 = 195 42 | MXM3_130 = 194 43 | MXM3_132 = 193 44 | MXM3_134 = 18 45 | MXM3_135 = 144 46 | MXM3_136 = 19 47 | MXM3_138 = 182 48 | MXM3_140 = 183 49 | MXM3_144 = 13 50 | MXM3_146 = 12 51 | MXM3_148 = 25 52 | MXM3_150 = 7 53 | MXM3_152 = 24 54 | MXM3_154 = 6 55 | MXM3_156 = 27 56 | MXM3_158 = 28 57 | MXM3_159 = 145 58 | MXM3_160 = 15 59 | MXM3_162 = 14 60 | MXM3_164 = 171 61 | MXM3_173 = 143 62 | MXM3_175 = 142 63 | MXM3_176 = 197 64 | MXM3_177 = 141 65 | MXM3_178 = 196 66 | MXM3_179 = 140 67 | MXM3_180 = 201 68 | MXM3_181 = 139 69 | MXM3_183 = 138 70 | MXM3_184 = 200 71 | MXM3_185 = 137 72 | MXM3_186 = 199 73 | MXM3_187 = 136 74 | MXM3_188 = 198 75 | MXM3_190 = 229 76 | MXM3_191 = 130 77 | MXM3_193 = 224 78 | MXM3_194 = 181 79 | MXM3_195 = 131 80 | MXM3_196 = 106 81 | MXM3_197 = 132 82 | MXM3_198 = 242 83 | MXM3_200 = 107 84 | MXM3_201 = 218 85 | MXM3_202 = 105 86 | MXM3_203 = 217 87 | MXM3_204 = 104 88 | MXM3_205 = 173 89 | MXM3_207 = 172 90 | MXM3_209 = 21 91 | MXM3_211 = 20 92 | MXM3_214 = 174 93 | MXM3_215 = 85 94 | MXM3_216 = 175 95 | MXM3_217 = 86 96 | MXM3_220 = 243 97 | MXM3_221 = 189 98 | MXM3_223 = 191 99 | MXM3_225 = 188 100 | MXM3_227 = 190 101 | MXM3_229 = 202 102 | MXM3_231 = 109 103 | MXM3_232 = 111 104 | MXM3_233 = 108 105 | MXM3_235 = 204 106 | MXM3_239 = 16 107 | MXM3_243 = 11 108 | MXM3_245 = 76 109 | MXM3_247 = 75 110 | MXM3_249 = 73 111 | MXM3_251 = 102 112 | MXM3_253 = 103 113 | MXM3_255 = 44 114 | MXM3_257 = 45 115 | MXM3_259 = 46 116 | MXM3_261 = 47 117 | MXM3_262 = 158 118 | MXM3_263 = 96 119 | MXM3_265 = 97 120 | MXM3_269 = 100 121 | MXM3_271 = 101 122 | MXM3_273 = 38 123 | MXM3_274 = 157 124 | MXM3_275 = 39 125 | MXM3_277 = 40 126 | MXM3_279 = 41 127 | MXM3_281 = 42 128 | MXM3_283 = 43 129 | MXM3_286 = 170 130 | MXM3_287 = 98 131 | MXM3_289 = 99 132 | MXM3_291 = 32 133 | MXM3_293 = 33 134 | MXM3_295 = 34 135 | MXM3_297 = 35 136 | MXM3_299 = 36 137 | MXM3_301 = 37 138 | -------------------------------------------------------------------------------- /contrib/board_files/apalis-tk1.conf: -------------------------------------------------------------------------------- 1 | # Toradex Apalis TK1 Computer On Module. 2 | # http://developer.toradex.com/products/apalis-tk1 3 | 4 | [board] 5 | dtfile = /proc/device-tree/model 6 | model = Toradex Apalis TK1 on Apalis Evaluation Board 7 | 8 | [GPIO] 9 | ###Apalis TK1 SODIMM number to GPIO number mapping 10 | 11 | MXM3_1 = 250 12 | MXM3_3 = 248 13 | MXM3_5 = 108 14 | MXM3_7 = 109 15 | MXM3_11 = 237 16 | MXM3_13 = 238 17 | MXM3_15 = 233 18 | MXM3_17 = 234 19 | MXM3_37 = 235 20 | MXM3_144 = 197 21 | MXM3_146 = 196 22 | MXM3_148 = 229 23 | MXM3_150 = 201 24 | MXM3_152 = 181 25 | MXM3_154 = 200 26 | MXM3_156 = 245 27 | MXM3_158 = 249 28 | MXM3_160 = 199 29 | MXM3_162 = 198 30 | MXM3_164 = 171 31 | MXM3_176 = 13 32 | MXM3_178 = 12 33 | MXM3_180 = 7 34 | MXM3_184 = 6 35 | MXM3_186 = 15 36 | MXM3_188 = 14 37 | MXM3_200 = 3 38 | MXM3_201 = 218 39 | MXM3_203 = 217 40 | MXM3_204 = 2 41 | MXM3_209 = 21 42 | MXM3_211 = 20 43 | MXM3_215 = 85 44 | MXM3_217 = 86 45 | MXM3_220 = 243 46 | MXM3_232 = 111 47 | -------------------------------------------------------------------------------- /contrib/board_files/artik_710.conf: -------------------------------------------------------------------------------- 1 | [board] 2 | model = Samsung ARTIK 710 3 | 4 | [GPIO] 5 | # https://developer.artik.io/documentation/developer-guide/gpio/ 6 | # gpio-mapping.html 7 | # and https://static.artik.io/files/SW_UserGuide_ARTIK-710_V1.0.pdf gave some 8 | # more clues, upon which I extrapolated -- jc at unternet dot net 9 | GPIOA0 = 0 10 | GPA0 = 0 11 | GPIO7 = 0 12 | GPIOA1 = 1 13 | GPA1 = 1 14 | GPIOA2 = 2 15 | GPA2 = 2 16 | GPIOA3 = 3 17 | GPA3 = 3 18 | GPIOA4 = 4 19 | GPA4 = 4 20 | GPIOA5 = 5 21 | GPA5 = 5 22 | GPIOA6 = 6 23 | GPA6 = 6 24 | GPIOA7 = 7 25 | GPA7 = 7 26 | GPIOA8 = 8 27 | GPA8 = 8 28 | GPIOA9 = 9 29 | GPA9 = 9 30 | GPIOA10 = 10 31 | GPA10 = 10 32 | GPIOA11 = 11 33 | GPA11 = 11 34 | GPIOA12 = 12 35 | GPA12 = 12 36 | GPIOA13 = 13 37 | GPA13 = 13 38 | GPIOA14 = 14 39 | GPA14 = 14 40 | GPIO4 = 14 41 | GPIOA15 = 15 42 | GPA15 = 15 43 | GPIOA16 = 16 44 | GPA16 = 16 45 | GPIOA17 = 17 46 | GPA17 = 17 47 | GPIOA18 = 18 48 | GPA18 = 18 49 | GPIOA19 = 19 50 | GPA19 = 19 51 | GPIOA20 = 20 52 | GPA20 = 20 53 | GPIOA21 = 21 54 | GPA21 = 21 55 | GPIOA22 = 22 56 | GPA22 = 22 57 | GPIOA23 = 23 58 | GPA23 = 23 59 | GPIOA24 = 24 60 | GPA24 = 24 61 | GPIOA25 = 25 62 | GPA25 = 25 63 | GPIO6 = 25 64 | GPIOA26 = 26 65 | GPA26 = 26 66 | GPIO8 = 26 67 | GPIOA27 = 27 68 | GPA27 = 27 69 | GPIO9 = 27 70 | GPIOA28 = 28 71 | GPA28 = 28 72 | RED_LED = 28 73 | GPIOA29 = 29 74 | GPA29 = 29 75 | GPIOA30 = 30 76 | GPA30 = 30 77 | SW403 = 30 78 | GPIOA31 = 31 79 | GPA31 = 31 80 | GPIOB0 = 32 81 | GPB0 = 32 82 | SW404 = 32 83 | GPIOB1 = 33 84 | GPB1 = 33 85 | GPIOB2 = 34 86 | GPB2 = 34 87 | GPIOB3 = 35 88 | GPB3 = 35 89 | GPIOB4 = 36 90 | GPB4 = 36 91 | GPIOB5 = 37 92 | GPB5 = 37 93 | GPIOB6 = 38 94 | GPB6 = 38 95 | BLUE_LED = 38 96 | GPIOB7 = 39 97 | GPB7 = 39 98 | GPIOB8 = 40 99 | GPB8 = 40 100 | GPIOB9 = 41 101 | GPB9 = 41 102 | GPIO5 = 41 103 | GPIOB10 = 42 104 | GPB10 = 42 105 | GPIOB11 = 43 106 | GPB11 = 43 107 | GPIOB12 = 44 108 | GPB12 = 44 109 | GPIOB13 = 45 110 | GPB13 = 45 111 | GPIOB14 = 46 112 | GPB14 = 46 113 | GPIO3 = 46 114 | GPIOB15 = 47 115 | GPB15 = 47 116 | GPIOB16 = 48 117 | GPB16 = 48 118 | GPIOB17 = 49 119 | GPB17 = 49 120 | GPIOB18 = 50 121 | GPB18 = 50 122 | GPIOB19 = 51 123 | GPB19 = 51 124 | GPIOB20 = 52 125 | GPB20 = 52 126 | GPIOB21 = 53 127 | GPB21 = 53 128 | GPIOB22 = 54 129 | GPB22 = 54 130 | GPIOB23 = 55 131 | GPB23 = 55 132 | GPIOB24 = 56 133 | GPB24 = 56 134 | GPIOB25 = 57 135 | GPB25 = 57 136 | GPIOB26 = 58 137 | GPB26 = 58 138 | GPIOB27 = 59 139 | GPB27 = 59 140 | GPIOB28 = 60 141 | GPB28 = 60 142 | UART0_RX = 60 143 | GPIOB29 = 61 144 | GPB29 = 61 145 | UART0_TX = 61 146 | GPIOB30 = 62 147 | GPB30 = 62 148 | GPIOB31 = 63 149 | GPB31 = 63 150 | GPIOC0 = 64 151 | GPC0 = 64 152 | GPIOC1 = 65 153 | GPC1 = 65 154 | GPIOC2 = 66 155 | GPC2 = 66 156 | GPIOC3 = 67 157 | GPC3 = 67 158 | GPIOC4 = 68 159 | GPC4 = 68 160 | GPIOC5 = 69 161 | GPC5 = 69 162 | GPIOC6 = 70 163 | GPC6 = 70 164 | GPIOC7 = 71 165 | GPC7 = 71 166 | GPIOC8 = 72 167 | GPC8 = 72 168 | GPIOC9 = 73 169 | GPC9 = 73 170 | SPI_CLK = 73 171 | GPIOC10 = 74 172 | GPC10 = 74 173 | SPI_CS = 74 174 | GPIOC11 = 75 175 | GPC11 = 75 176 | SPI_MISO = 75 177 | GPIOC12 = 76 178 | GPC12 = 76 179 | SPI_MOSI = 76 180 | GPIOC13 = 77 181 | GPC13 = 77 182 | GPIOC14 = 78 183 | GPC14 = 78 184 | GPIOC15 = 79 185 | GPC15 = 79 186 | GPIOC16 = 80 187 | GPC16 = 80 188 | GPIOC17 = 81 189 | GPC17 = 81 190 | GPIOC18 = 82 191 | GPC18 = 82 192 | GPIOC19 = 83 193 | GPC19 = 83 194 | GPIOC20 = 84 195 | GPC20 = 84 196 | GPIOC21 = 85 197 | GPC21 = 85 198 | GPIOC22 = 86 199 | GPC22 = 86 200 | GPIOC23 = 87 201 | GPC23 = 87 202 | GPIOC24 = 88 203 | GPC24 = 88 204 | GPIOC25 = 89 205 | GPC25 = 89 206 | GPIOC26 = 90 207 | GPC26 = 90 208 | GPIOC27 = 91 209 | GPC27 = 91 210 | GPIOC28 = 92 211 | GPC28 = 92 212 | GPIOC29 = 93 213 | GPC29 = 93 214 | GPIOC30 = 94 215 | GPC30 = 94 216 | GPIOC31 = 95 217 | GPC31 = 95 218 | GPIOD0 = 96 219 | GPD0 = 96 220 | GPIOD1 = 97 221 | GPD1 = 97 222 | GPIOD2 = 98 223 | GPD2 = 98 224 | GPIOD3 = 99 225 | GPD3 = 99 226 | GPIOD4 = 100 227 | GPD4 = 100 228 | I2C_SCL = 100 229 | GPIOD5 = 101 230 | GPD5 = 101 231 | I2C_SDA = 101 232 | GPIOD6 = 102 233 | GPD6 = 102 234 | GPIOD7 = 103 235 | GPD7 = 103 236 | GPIOD8 = 104 237 | GPD8 = 104 238 | GPIOD9 = 105 239 | GPD9 = 105 240 | GPIOD10 = 106 241 | GPD10 = 106 242 | GPIOD11 = 107 243 | GPD11 = 107 244 | GPIOD12 = 108 245 | GPD12 = 108 246 | GPIOD13 = 109 247 | GPD13 = 109 248 | GPIOD14 = 110 249 | GPD14 = 110 250 | GPIOD15 = 111 251 | GPD15 = 111 252 | GPIOD16 = 112 253 | GPD16 = 112 254 | GPIOD17 = 113 255 | GPD17 = 113 256 | GPIOD18 = 114 257 | GPD18 = 114 258 | GPIOD19 = 115 259 | GPD19 = 115 260 | GPIOD20 = 116 261 | GPD20 = 116 262 | GPIOD21 = 117 263 | GPD21 = 117 264 | GPIOD22 = 118 265 | GPD22 = 118 266 | GPIOD23 = 119 267 | GPD23 = 119 268 | GPIOD24 = 120 269 | GPD24 = 120 270 | GPIOD25 = 121 271 | GPD25 = 121 272 | GPIOD26 = 122 273 | GPD26 = 122 274 | GPIOD27 = 123 275 | GPD27 = 123 276 | GPIOD28 = 124 277 | GPD28 = 124 278 | GPIOD29 = 125 279 | GPD29 = 125 280 | GPIOD30 = 126 281 | GPD30 = 126 282 | GPIOD31 = 127 283 | GPD31 = 127 284 | GPIOE0 = 128 285 | GPE0 = 128 286 | GPIO0 = 128 287 | GPIOE1 = 129 288 | GPE1 = 129 289 | GPIO1 = 129 290 | GPIOE2 = 130 291 | GPE2 = 130 292 | GPIO2 = 130 293 | GPIOE3 = 131 294 | GPE3 = 131 295 | GPIOE4 = 132 296 | GPE4 = 132 297 | GPIOE5 = 133 298 | GPE5 = 133 299 | GPIOE6 = 134 300 | GPE6 = 134 301 | GPIOE7 = 135 302 | GPE7 = 135 303 | GPIOE8 = 136 304 | GPE8 = 136 305 | GPIOE9 = 137 306 | GPE9 = 137 307 | GPIOE10 = 138 308 | GPE10 = 138 309 | GPIOE11 = 139 310 | GPE11 = 139 311 | GPIOE12 = 140 312 | GPE12 = 140 313 | GPIOE13 = 141 314 | GPE13 = 141 315 | GPIOE14 = 142 316 | GPE14 = 142 317 | GPIOE15 = 143 318 | GPE15 = 143 319 | GPIOE16 = 144 320 | GPE16 = 144 321 | GPIOE17 = 145 322 | GPE17 = 145 323 | GPIOE18 = 146 324 | GPE18 = 146 325 | GPIOE19 = 147 326 | GPE19 = 147 327 | GPIOE20 = 148 328 | GPE20 = 148 329 | GPIOE21 = 149 330 | GPE21 = 149 331 | GPIOE22 = 150 332 | GPE22 = 150 333 | GPIOE23 = 151 334 | GPE23 = 151 335 | GPIOE24 = 152 336 | GPE24 = 152 337 | GPIOE25 = 153 338 | GPE25 = 153 339 | GPIOE26 = 154 340 | GPE26 = 154 341 | GPIOE27 = 155 342 | GPE27 = 155 343 | GPIOE28 = 156 344 | GPE28 = 156 345 | GPIOE29 = 157 346 | GPE29 = 157 347 | GPIOE30 = 158 348 | GPE30 = 158 349 | GPIOE31 = 159 350 | GPE31 = 159 351 | AGPIO0 = 161 352 | ALIVE1 = 161 353 | -------------------------------------------------------------------------------- /contrib/board_files/beaglebone_black.conf: -------------------------------------------------------------------------------- 1 | [board] 2 | model = TI AM335x BeagleBone Black 3 | 4 | [GPIO] 5 | # beaglebone pin layout 6 | # http://beagleboard.org/support/bone101 7 | # 8 | P9_11 = 30 9 | P9_12 = 60 10 | P9_13 = 31 11 | P9_14 = 50 12 | P9_15 = 48 13 | P9_16 = 51 14 | P9_17 = 5 15 | P9_18 = 4 16 | P9_21 = 3 17 | P9_22 = 2 18 | P9_23 = 49 19 | P9_24 = 15 20 | P9_25 = 117 21 | P9_26 = 14 22 | P9_27 = 115 23 | P9_28 = 113 24 | P9_29 = 111 25 | P9_30 = 112 26 | P9_31 = 110 27 | P9_41 = 116 28 | P9_42 = 7 29 | 30 | P8_3 = 38 31 | P8_4 = 39 32 | P8_5 = 34 33 | P8_6 = 35 34 | P8_7 = 66 35 | P8_8 = 67 36 | P8_9 = 69 37 | P8_10 = 68 38 | P8_11 = 45 39 | P8_12 = 44 40 | P8_13 = 23 41 | P8_14 = 26 42 | P8_15 = 47 43 | P8_16 = 46 44 | P8_17 = 27 45 | P8_18 = 65 46 | P8_19 = 22 47 | P8_20 = 63 48 | P8_21 = 62 49 | P8_22 = 37 50 | P8_23 = 36 51 | P8_24 = 33 52 | P8_25 = 32 53 | P8_26 = 61 54 | P8_27 = 86 55 | P8_28 = 88 56 | P8_29 = 87 57 | P8_30 = 89 58 | P8_31 = 10 59 | P8_32 = 11 60 | P8_33 = 9 61 | P8_34 = 81 62 | P8_35 = 8 63 | P8_36 = 80 64 | P8_37 = 78 65 | P8_38 = 79 66 | P8_39 = 76 67 | P8_40 = 77 68 | P8_41 = 74 69 | P8_42 = 75 70 | P8_43 = 72 71 | P8_44 = 73 72 | P8_45 = 70 73 | P8_46 = 71 74 | 75 | # https://github.com/CircuitCo/BeagleBone-Black/blob/rev_b/BBB_SRM.pdf 76 | # calculate GPIO IDs from GPIOn_mm (e.g. GPIO1_21) as (n * 32) + mm 77 | 78 | GPIO1_21 = 53 79 | LED_USR0 = 53 80 | GPIO1_22 = 54 81 | LED_USR1 = 54 82 | GPIO1_23 = 55 83 | LED_USR2 = 55 84 | GPIO1_24 = 56 85 | LED_USR3 = 56 86 | GPIO2_8 = 72 87 | LCD_DATA2 = 72 88 | BOOT_BUTTON = 72 89 | S2 = 72 90 | -------------------------------------------------------------------------------- /contrib/board_files/bubblegum.conf: -------------------------------------------------------------------------------- 1 | [board] 2 | model = s900 3 | 4 | [GPIO] 5 | # bubblegum pin layout 6 | # 7 | GPIO-A = 0 8 | GPIO-B = 1 9 | GPIO-C = 2 10 | GPIO-D = 3 11 | GPIO-E = 4 12 | GPIO-F = 5 13 | GPIO-G = 6 14 | GPIO-H = 7 15 | GPIO-I = 8 16 | GPIO-J = 9 17 | GPIO-K = 155 18 | GPIO-L = 154 19 | 20 | # include mappings by pin number on board 21 | GPIO-23 = 0 22 | GPIO-24 = 1 23 | GPIO-25 = 2 24 | GPIO-26 = 3 25 | GPIO-27 = 4 26 | GPIO-28 = 5 27 | GPIO-29 = 6 28 | GPIO-30 = 7 29 | GPIO-31 = 8 30 | GPIO-32 = 9 31 | GPIO-33 = 155 32 | GPIO-34 = 154 33 | 34 | 35 | -------------------------------------------------------------------------------- /contrib/board_files/chip.conf: -------------------------------------------------------------------------------- 1 | [board] 2 | model = C.H.I.P with 4.3 kernel 3 | 4 | [GPIO] 5 | #C.H.I.P. pin layout by Next Thing Co. 6 | # 7 | 8 | # From: http://www.chip-community.org/index.php/GPIO_Info 9 | PWM0 = 34 10 | AP-EINT3 = 35 11 | TWI1-SCK = 47 12 | TWI1-SDA = 48 13 | TWI2-SCK = 49 14 | TWI2-SDA = 50 15 | LCD-D2 = 98 16 | LCD-D3 = 99 17 | LCD-D4 = 100 18 | LCD-D5 = 101 19 | LCD-D6 = 102 20 | LCD-D7 = 103 21 | LCD-D10 = 106 22 | LCD-D11 = 107 23 | LCD-D12 = 108 24 | LCD-D13 = 109 25 | LCD-D14 = 110 26 | LCD-D15 = 111 27 | LCD-D18 = 114 28 | LCD-D19 = 115 29 | LCD-D20 = 116 30 | LCD-D21 = 117 31 | LCD-D22 = 118 32 | LCD-D23 = 119 33 | LCD-CLK = 120 34 | LCD-DE = 121 35 | LCD-HSYNC = 122 36 | LCD-VSYNC = 123 37 | CSIPCK = 128 38 | CSICK = 129 39 | CSIHSYNC = 130 40 | CSIVSYNC = 131 41 | CSID0 = 132 42 | CSID1 = 133 43 | CSID2 = 134 44 | CSID3 = 135 45 | CSID4 = 136 46 | CSID5 = 137 47 | CSID6 = 138 48 | CSID7 = 139 49 | AP-EINT1 = 193 50 | UART1-TX = 195 51 | UART1-RX = 196 52 | 53 | # (4.4) 54 | XIO-P0 = 408 # 1016 55 | XIO-P1 = 409 # 1017 56 | XIO-P2 = 410 # 1018 57 | XIO-P3 = 411 # 1019 58 | XIO-P4 = 412 # 1020 59 | XIO-P5 = 413 # 1021 60 | XIO-P6 = 414 # 1022 61 | XIO-P7 = 415 # 1023 62 | -------------------------------------------------------------------------------- /contrib/board_files/colibri-imx6.conf: -------------------------------------------------------------------------------- 1 | # Toradex Colibri iMX6 Computer On Module. 2 | # http://developer.toradex.com/products/colibri-imx6 3 | 4 | [board] 5 | dtfile = /proc/device-tree/model 6 | model = Toradex Colibri iMX6 on Colibri Evaluation Board 7 | 8 | [GPIO] 9 | ###Colibri IMX6 SODIMM number to GPIO number mapping 10 | 11 | SODIMM_19 = 201 12 | SODIMM_21 = 202 13 | SODIMM_22 = 23 14 | SODIMM_23 = 88 15 | SODIMM_24 = 116 16 | SODIMM_25 = 83 17 | SODIMM_27 = 84 18 | SODIMM_28 = 9 19 | SODIMM_29 = 89 20 | SODIMM_30 = 42 21 | SODIMM_31 = 87 22 | SODIMM_32 = 46 23 | SODIMM_33 = 156 24 | SODIMM_34 = 45 25 | SODIMM_35 = 157 26 | SODIMM_36 = 47 27 | SODIMM_37 = 39 28 | SODIMM_38 = 44 29 | SODIMM_43 = 37 30 | SODIMM_44 = 113 31 | SODIMM_45 = 54 32 | SODIMM_46 = 124 33 | SODIMM_47 = 20 34 | SODIMM_48 = 126 35 | SODIMM_49 = 17 36 | SODIMM_50 = 133 37 | SODIMM_51 = 19 38 | SODIMM_52 = 134 39 | SODIMM_53 = 21 40 | SODIMM_54 = 135 41 | SODIMM_55 = 7 42 | SODIMM_56 = 112 43 | SODIMM_57 = 138 44 | SODIMM_58 = 120 45 | SODIMM_59 = 41 46 | SODIMM_59# = 48 47 | SODIMM_60 = 119 48 | SODIMM_61 = 139 49 | SODIMM_62 = 125 50 | SODIMM_63 = 8 51 | SODIMM_64 = 137 52 | SODIMM_65 = 132 53 | SODIMM_66 = 136 54 | SODIMM_67 = 1 55 | SODIMM_67# = 49 56 | SODIMM_68 = 114 57 | SODIMM_69 = 11 58 | SODIMM_70 = 118 59 | SODIMM_71 = 90 60 | SODIMM_72 = 122 61 | SODIMM_73 = 91 62 | SODIMM_74 = 127 63 | SODIMM_75 = 175 64 | SODIMM_76 = 117 65 | SODIMM_77 = 82 66 | SODIMM_78 = 121 67 | SODIMM_79 = 51 68 | SODIMM_80 = 123 69 | SODIMM_81 = 93 70 | SODIMM_82 = 115 71 | SODIMM_85 = 166 72 | SODIMM_86 = 130 73 | SODIMM_88 = 85 74 | SODIMM_89 = 58 75 | SODIMM_90 = 86 76 | SODIMM_91 = 57 77 | SODIMM_92 = 92 78 | SODIMM_93 = 10 79 | SODIMM_94 = 63 80 | SODIMM_95 = 128 81 | SODIMM_96 = 81 82 | SODIMM_97 = 50 83 | SODIMM_98 = 15 84 | SODIMM_99 = 12 85 | SODIMM_100 = 43 86 | SODIMM_101 = 53 87 | SODIMM_102 = 36 88 | SODIMM_103 = 52 89 | SODIMM_104 = 40 90 | SODIMM_105 = 55 91 | SODIMM_106 = 14 92 | SODIMM_107 = 56 93 | SODIMM_110 = 72 94 | SODIMM_111 = 64 95 | SODIMM_112 = 73 96 | SODIMM_113 = 65 97 | SODIMM_114 = 74 98 | SODIMM_115 = 66 99 | SODIMM_116 = 75 100 | SODIMM_117 = 67 101 | SODIMM_118 = 76 102 | SODIMM_119 = 68 103 | SODIMM_120 = 77 104 | SODIMM_121 = 69 105 | SODIMM_122 = 78 106 | SODIMM_123 = 70 107 | SODIMM_124 = 79 108 | SODIMM_125 = 71 109 | SODIMM_126 = 60 110 | SODIMM_127 = 38 111 | SODIMM_128 = 61 112 | SODIMM_129 = 95 113 | SODIMM_130 = 13 114 | SODIMM_131 = 94 115 | SODIMM_132 = 32 116 | SODIMM_133 = 35 117 | SODIMM_134 = 33 118 | SODIMM_135 = 34 119 | SODIMM_136 = 140 120 | SODIMM_137 = 204 121 | SODIMM_138 = 141 122 | SODIMM_140 = 142 123 | SODIMM_142 = 143 124 | SODIMM_144 = 144 125 | SODIMM_146 = 145 126 | SODIMM_149 = 148 127 | SODIMM_150 = 59 128 | SODIMM_151 = 149 129 | SODIMM_152 = 191 130 | SODIMM_153 = 150 131 | SODIMM_154 = 176 132 | SODIMM_155 = 151 133 | SODIMM_156 = 174 134 | SODIMM_157 = 152 135 | SODIMM_158 = 170 136 | SODIMM_159 = 153 137 | SODIMM_160 = 168 138 | SODIMM_161 = 154 139 | SODIMM_162 = 169 140 | SODIMM_163 = 155 141 | SODIMM_164 = 171 142 | SODIMM_165 = 158 143 | SODIMM_166 = 167 144 | SODIMM_167 = 159 145 | SODIMM_168 = 101 146 | SODIMM_169 = 160 147 | SODIMM_170 = 147 148 | SODIMM_171 = 161 149 | SODIMM_172 = 146 150 | SODIMM_173 = 162 151 | SODIMM_174 = 4 152 | SODIMM_175 = 163 153 | SODIMM_176 = 5 154 | SODIMM_177 = 164 155 | SODIMM_178 = 110 156 | SODIMM_179 = 165 157 | SODIMM_180 = 2 158 | SODIMM_184 = 106 159 | SODIMM_186 = 107 160 | SODIMM_188 = 111 161 | SODIMM_190 = 18 162 | SODIMM_192 = 16 163 | SODIMM_194 = 6 164 | SODIMM_196 = 3 165 | SODIMM_15 = 108 166 | SODIMM_16 = 109 167 | -------------------------------------------------------------------------------- /contrib/board_files/colibri-imx6ull.conf: -------------------------------------------------------------------------------- 1 | # Toradex Colibri iMX6ULL Computer On Module. 2 | # http://developer.toradex.com/products/colibri-imx6ull 3 | 4 | [board] 5 | dtfile = /proc/device-tree/model 6 | model = Toradex Colibri iMX6ULL on Colibri Evaluation Board 7 | 8 | [GPIO] 9 | ###Colibri IMX6ULL SODIMM number to GPIO number mapping 10 | 11 | SODIMM_2 = 9 12 | SODIMM_4 = 8 13 | SODIMM_6 = 1 14 | SODIMM_8 = 0 15 | SODIMM_19 = 4 16 | SODIMM_21 = 5 17 | SODIMM_23 = 12 18 | SODIMM_25 = 18 19 | SODIMM_27 = 19 20 | SODIMM_28 = 112 21 | SODIMM_29 = 87 22 | SODIMM_30 = 37 23 | SODIMM_31 = 13 24 | SODIMM_32 = 22 25 | SODIMM_33 = 16 26 | SODIMM_34 = 23 27 | SODIMM_35 = 17 28 | SODIMM_36 = 20 29 | SODIMM_37 = 88 30 | SODIMM_38 = 21 31 | SODIMM_43 = 128 32 | SODIMM_44 = 65 33 | SODIMM_45 = 129 34 | SODIMM_46 = 76 35 | SODIMM_47 = 49 36 | SODIMM_48 = 78 37 | SODIMM_49 = 51 38 | SODIMM_50 = 80 39 | SODIMM_51 = 52 40 | SODIMM_52 = 81 41 | SODIMM_53 = 53 42 | SODIMM_54 = 82 43 | SODIMM_55 = 32 44 | SODIMM_56 = 64 45 | SODIMM_57 = 85 46 | SODIMM_58 = 72 47 | SODIMM_59 = 107 48 | SODIMM_60 = 71 49 | SODIMM_61 = 86 50 | SODIMM_62 = 77 51 | SODIMM_63 = 33 52 | SODIMM_64 = 84 53 | SODIMM_65 = 124 54 | SODIMM_66 = 83 55 | SODIMM_67 = 38 56 | SODIMM_68 = 66 57 | SODIMM_69 = 121 58 | SODIMM_70 = 70 59 | SODIMM_71 = 11 60 | SODIMM_72 = 74 61 | SODIMM_73 = 36 62 | SODIMM_74 = 79 63 | SODIMM_75 = 113 64 | SODIMM_76 = 69 65 | SODIMM_77 = 25 66 | SODIMM_78 = 73 67 | SODIMM_79 = 119 68 | SODIMM_80 = 75 69 | SODIMM_81 = 115 70 | SODIMM_82 = 67 71 | SODIMM_85 = 123 72 | SODIMM_86 = 90 73 | SODIMM_88 = 89 74 | SODIMM_89 = 3 75 | SODIMM_90 = 92 76 | SODIMM_92 = 91 77 | SODIMM_93 = 134 78 | SODIMM_94 = 116 79 | SODIMM_95 = 131 80 | SODIMM_96 = 114 81 | SODIMM_97 = 120 82 | SODIMM_98 = 122 83 | SODIMM_99 = 14 84 | SODIMM_100 = 26 85 | SODIMM_101 = 117 86 | SODIMM_102 = 15 87 | SODIMM_103 = 118 88 | SODIMM_104 = 39 89 | SODIMM_105 = 138 90 | SODIMM_106 = 10 91 | SODIMM_107 = 132 92 | SODIMM_127 = 139 93 | SODIMM_129 = 2 94 | SODIMM_131 = 133 95 | SODIMM_133 = 110 96 | SODIMM_135 = 24 97 | SODIMM_137 = 130 98 | SODIMM_138 = 136 99 | SODIMM_178 = 34 100 | SODIMM_186 = 27 101 | SODIMM_188 = 35 102 | SODIMM_190 = 48 103 | SODIMM_192 = 50 104 | SODIMM_194 = 29 105 | SODIMM_196 = 28 106 | -------------------------------------------------------------------------------- /contrib/board_files/colibri-imx6ullwb.conf: -------------------------------------------------------------------------------- 1 | # Toradex Colibri iMX6ULLWB Computer On Module. 2 | # http://developer.toradex.com/products/colibri-imx6ullwb 3 | 4 | [board] 5 | dtfile = /proc/device-tree/model 6 | model = Toradex Colibri iMX6ULLWB on Colibri Evaluation Board 7 | 8 | [GPIO] 9 | ###Colibri IMX6ULLWB SODIMM number to GPIO number mapping 10 | 11 | SODIMM_2 = 9 12 | SODIMM_4 = 8 13 | SODIMM_6 = 1 14 | SODIMM_8 = 0 15 | SODIMM_19 = 4 16 | SODIMM_21 = 5 17 | SODIMM_23 = 12 18 | SODIMM_25 = 18 19 | SODIMM_27 = 19 20 | SODIMM_28 = 112 21 | SODIMM_29 = 87 22 | SODIMM_30 = 37 23 | SODIMM_31 = 13 24 | SODIMM_32 = 22 25 | SODIMM_33 = 16 26 | SODIMM_34 = 23 27 | SODIMM_35 = 17 28 | SODIMM_36 = 20 29 | SODIMM_37 = 88 30 | SODIMM_38 = 21 31 | SODIMM_43 = 128 32 | SODIMM_44 = 65 33 | SODIMM_45 = 129 34 | SODIMM_46 = 76 35 | SODIMM_47 = 49 36 | SODIMM_48 = 78 37 | SODIMM_49 = 51 38 | SODIMM_50 = 80 39 | SODIMM_51 = 52 40 | SODIMM_52 = 81 41 | SODIMM_53 = 53 42 | SODIMM_54 = 82 43 | SODIMM_55 = 32 44 | SODIMM_56 = 64 45 | SODIMM_57 = 85 46 | SODIMM_58 = 72 47 | SODIMM_59 = 107 48 | SODIMM_60 = 71 49 | SODIMM_61 = 86 50 | SODIMM_62 = 77 51 | SODIMM_63 = 33 52 | SODIMM_64 = 84 53 | SODIMM_65 = 124 54 | SODIMM_66 = 83 55 | SODIMM_67 = 38 56 | SODIMM_68 = 66 57 | SODIMM_69 = 121 58 | SODIMM_70 = 70 59 | SODIMM_71 = 11 60 | SODIMM_72 = 74 61 | SODIMM_73 = 36 62 | SODIMM_74 = 79 63 | SODIMM_75 = 113 64 | SODIMM_76 = 69 65 | SODIMM_77 = 25 66 | SODIMM_78 = 73 67 | SODIMM_80 = 75 68 | SODIMM_82 = 67 69 | SODIMM_85 = 123 70 | SODIMM_86 = 90 71 | SODIMM_88 = 89 72 | SODIMM_90 = 92 73 | SODIMM_92 = 91 74 | SODIMM_95 = 131 75 | SODIMM_96 = 114 76 | SODIMM_98 = 122 77 | SODIMM_99 = 14 78 | SODIMM_100 = 26 79 | SODIMM_102 = 15 80 | SODIMM_104 = 39 81 | SODIMM_105 = 138 82 | SODIMM_106 = 10 83 | SODIMM_107 = 132 84 | SODIMM_129 = 2 85 | SODIMM_131 = 133 86 | SODIMM_133 = 110 87 | SODIMM_135 = 24 88 | SODIMM_137 = 130 89 | SODIMM_178 = 34 90 | SODIMM_186 = 27 91 | SODIMM_188 = 35 92 | SODIMM_190 = 48 93 | SODIMM_192 = 50 94 | SODIMM_194 = 29 95 | SODIMM_196 = 28 96 | -------------------------------------------------------------------------------- /contrib/board_files/colibri-imx7-1GB.conf: -------------------------------------------------------------------------------- 1 | # Toradex Colibri iMX7 Computer On Module. 2 | # http://developer.toradex.com/products/colibri-imx7 3 | 4 | [board] 5 | dtfile = /proc/device-tree/model 6 | model = Toradex Colibri iMX7 on Colibri Evaluation Board 7 | 8 | [GPIO] 9 | ###Colibri IMX7 SODIMM number to GPIO number mapping 10 | 11 | SODIMM_19 = 101 12 | SODIMM_21 = 100 13 | SODIMM_22 = 3 14 | SODIMM_23 = 142 15 | SODIMM_24 = 177 16 | SODIMM_25 = 179 17 | SODIMM_27 = 180 18 | SODIMM_28 = 9 19 | SODIMM_29 = 7 20 | SODIMM_30 = 10 21 | SODIMM_31 = 143 22 | SODIMM_32 = 181 23 | SODIMM_33 = 97 24 | SODIMM_34 = 182 25 | SODIMM_35 = 96 26 | SODIMM_36 = 99 27 | SODIMM_37 = 6 28 | SODIMM_38 = 98 29 | SODIMM_43 = 0 30 | SODIMM_44 = 65 31 | SODIMM_45 = 1 32 | SODIMM_46 = 76 33 | SODIMM_47 = 131 34 | SODIMM_48 = 78 35 | SODIMM_49 = 134 36 | SODIMM_50 = 80 37 | SODIMM_51 = 135 38 | SODIMM_52 = 81 39 | SODIMM_53 = 136 40 | SODIMM_54 = 82 41 | SODIMM_55 = 195 42 | SODIMM_56 = 64 43 | SODIMM_57 = 85 44 | SODIMM_58 = 72 45 | SODIMM_59 = 8 46 | SODIMM_59# = 117 47 | SODIMM_60 = 71 48 | SODIMM_61 = 86 49 | SODIMM_62 = 77 50 | SODIMM_63 = 194 51 | SODIMM_64 = 84 52 | SODIMM_65 = 119 53 | SODIMM_66 = 83 54 | SODIMM_67 = 11 55 | SODIMM_67# = 116 56 | SODIMM_68 = 66 57 | SODIMM_69 = 128 58 | SODIMM_70 = 70 59 | SODIMM_71 = 129 60 | SODIMM_72 = 74 61 | SODIMM_73 = 130 62 | SODIMM_74 = 79 63 | SODIMM_75 = 111 64 | SODIMM_76 = 69 65 | SODIMM_77 = 176 66 | SODIMM_78 = 73 67 | SODIMM_79 = 114 68 | SODIMM_80 = 75 69 | SODIMM_81 = 108 70 | SODIMM_82 = 67 71 | SODIMM_85 = 118 72 | SODIMM_86 = 107 73 | SODIMM_88 = 106 74 | SODIMM_89 = 41 75 | SODIMM_90 = 104 76 | SODIMM_91 = 40 77 | SODIMM_92 = 105 78 | SODIMM_93 = 68 79 | SODIMM_94 = 109 80 | SODIMM_95 = 45 81 | SODIMM_96 = 110 82 | SODIMM_97 = 115 83 | SODIMM_98 = 139 84 | SODIMM_99 = 203 85 | SODIMM_100 = 144 86 | SODIMM_101 = 112 87 | SODIMM_102 = 145 88 | SODIMM_103 = 113 89 | SODIMM_104 = 59 90 | SODIMM_105 = 42 91 | SODIMM_106 = 60 92 | SODIMM_107 = 47 93 | SODIMM_110 = 61 94 | SODIMM_111 = 32 95 | SODIMM_112 = 62 96 | SODIMM_113 = 33 97 | SODIMM_114 = 48 98 | SODIMM_115 = 34 99 | SODIMM_116 = 49 100 | SODIMM_117 = 35 101 | SODIMM_118 = 50 102 | SODIMM_119 = 36 103 | SODIMM_120 = 51 104 | SODIMM_121 = 37 105 | SODIMM_122 = 52 106 | SODIMM_123 = 38 107 | SODIMM_124 = 53 108 | SODIMM_125 = 39 109 | SODIMM_126 = 46 110 | SODIMM_127 = 54 111 | SODIMM_128 = 63 112 | SODIMM_129 = 103 113 | SODIMM_130 = 55 114 | SODIMM_131 = 102 115 | SODIMM_132 = 56 116 | SODIMM_133 = 58 117 | SODIMM_134 = 57 118 | SODIMM_135 = 2 119 | SODIMM_136 = 87 120 | SODIMM_137 = 206 121 | SODIMM_138 = 88 122 | SODIMM_140 = 89 123 | SODIMM_142 = 90 124 | SODIMM_144 = 91 125 | SODIMM_146 = 92 126 | SODIMM_150 = 44 127 | SODIMM_152 = 43 128 | SODIMM_157 = 173 129 | SODIMM_163 = 175 130 | SODIMM_169 = 172 131 | SODIMM_178 = 15 132 | SODIMM_184 = 140 133 | SODIMM_186 = 141 134 | SODIMM_188 = 14 135 | SODIMM_190 = 132 136 | SODIMM_192 = 133 137 | SODIMM_194 = 201 138 | SODIMM_196 = 200 139 | -------------------------------------------------------------------------------- /contrib/board_files/colibri-imx7-512mb.conf: -------------------------------------------------------------------------------- 1 | # Toradex Colibri iMX7 Computer On Module. 2 | # http://developer.toradex.com/products/colibri-imx7 3 | 4 | [board] 5 | dtfile = /proc/device-tree/model 6 | model = Toradex Colibri iMX7 on Colibri Evaluation Board 7 | 8 | [GPIO] 9 | ###Colibri IMX7 SODIMM number to GPIO number mapping 10 | 11 | SODIMM_19 = 101 12 | SODIMM_21 = 100 13 | SODIMM_22 = 3 14 | SODIMM_23 = 142 15 | SODIMM_24 = 177 16 | SODIMM_25 = 179 17 | SODIMM_27 = 180 18 | SODIMM_28 = 9 19 | SODIMM_29 = 7 20 | SODIMM_30 = 10 21 | SODIMM_31 = 143 22 | SODIMM_32 = 181 23 | SODIMM_33 = 97 24 | SODIMM_34 = 182 25 | SODIMM_35 = 96 26 | SODIMM_36 = 99 27 | SODIMM_37 = 6 28 | SODIMM_38 = 98 29 | SODIMM_43 = 0 30 | SODIMM_44 = 65 31 | SODIMM_45 = 1 32 | SODIMM_46 = 76 33 | SODIMM_47 = 131 34 | SODIMM_48 = 78 35 | SODIMM_49 = 134 36 | SODIMM_50 = 80 37 | SODIMM_51 = 135 38 | SODIMM_52 = 81 39 | SODIMM_53 = 136 40 | SODIMM_54 = 82 41 | SODIMM_55 = 195 42 | SODIMM_56 = 64 43 | SODIMM_57 = 85 44 | SODIMM_58 = 72 45 | SODIMM_59 = 8 46 | SODIMM_59# = 117 47 | SODIMM_60 = 71 48 | SODIMM_61 = 86 49 | SODIMM_62 = 77 50 | SODIMM_63 = 194 51 | SODIMM_64 = 84 52 | SODIMM_65 = 119 53 | SODIMM_66 = 83 54 | SODIMM_67 = 11 55 | SODIMM_67# = 116 56 | SODIMM_68 = 66 57 | SODIMM_69 = 128 58 | SODIMM_70 = 70 59 | SODIMM_71 = 129 60 | SODIMM_72 = 74 61 | SODIMM_73 = 130 62 | SODIMM_74 = 79 63 | SODIMM_75 = 111 64 | SODIMM_76 = 69 65 | SODIMM_77 = 176 66 | SODIMM_78 = 73 67 | SODIMM_79 = 114 68 | SODIMM_80 = 75 69 | SODIMM_81 = 108 70 | SODIMM_82 = 67 71 | SODIMM_85 = 118 72 | SODIMM_86 = 107 73 | SODIMM_88 = 106 74 | SODIMM_89 = 41 75 | SODIMM_90 = 104 76 | SODIMM_91 = 40 77 | SODIMM_92 = 105 78 | SODIMM_93 = 68 79 | SODIMM_94 = 109 80 | SODIMM_95 = 45 81 | SODIMM_96 = 110 82 | SODIMM_97 = 115 83 | SODIMM_98 = 139 84 | SODIMM_99 = 203 85 | SODIMM_100 = 144 86 | SODIMM_101 = 112 87 | SODIMM_102 = 145 88 | SODIMM_103 = 113 89 | SODIMM_104 = 59 90 | SODIMM_105 = 42 91 | SODIMM_106 = 60 92 | SODIMM_107 = 47 93 | SODIMM_110 = 61 94 | SODIMM_111 = 32 95 | SODIMM_112 = 62 96 | SODIMM_113 = 33 97 | SODIMM_114 = 48 98 | SODIMM_115 = 34 99 | SODIMM_116 = 49 100 | SODIMM_117 = 35 101 | SODIMM_118 = 50 102 | SODIMM_119 = 36 103 | SODIMM_120 = 51 104 | SODIMM_121 = 37 105 | SODIMM_122 = 52 106 | SODIMM_123 = 38 107 | SODIMM_124 = 53 108 | SODIMM_125 = 39 109 | SODIMM_126 = 46 110 | SODIMM_127 = 54 111 | SODIMM_128 = 63 112 | SODIMM_129 = 103 113 | SODIMM_130 = 55 114 | SODIMM_131 = 102 115 | SODIMM_132 = 56 116 | SODIMM_133 = 58 117 | SODIMM_134 = 57 118 | SODIMM_135 = 2 119 | SODIMM_136 = 87 120 | SODIMM_137 = 206 121 | SODIMM_138 = 88 122 | SODIMM_140 = 89 123 | SODIMM_142 = 90 124 | SODIMM_144 = 91 125 | SODIMM_146 = 92 126 | SODIMM_150 = 44 127 | SODIMM_152 = 43 128 | SODIMM_169 = 172 129 | SODIMM_178 = 15 130 | SODIMM_184 = 140 131 | SODIMM_186 = 141 132 | SODIMM_188 = 14 133 | SODIMM_190 = 132 134 | SODIMM_192 = 133 135 | SODIMM_194 = 201 136 | SODIMM_196 = 200 137 | -------------------------------------------------------------------------------- /contrib/board_files/colibri-t20.conf: -------------------------------------------------------------------------------- 1 | # Toradex Colibri T20 Computer On Module. 2 | # http://developer.toradex.com/products/colibri-t20 3 | 4 | [board] 5 | dtfile = /proc/device-tree/model 6 | model = Toradex Colibri T20 on Colibri Evaluation Board 7 | 8 | [GPIO] 9 | ###Colibri T20 SODIMM number to GPIO number mapping 10 | 11 | SODIMM_19 = 19 12 | SODIMM_21 = 18 13 | SODIMM_22 = 220 14 | SODIMM_23 = 200 15 | SODIMM_24 = 221 16 | SODIMM_25 = 201 17 | SODIMM_27 = 199 18 | SODIMM_28 = 13 19 | SODIMM_29 = 17 20 | SODIMM_30 = 6 21 | SODIMM_31 = 22 22 | SODIMM_32 = 9 23 | SODIMM_33 = 197 24 | SODIMM_34 = 87 25 | SODIMM_35 = 196 26 | SODIMM_36 = 8 27 | SODIMM_37 = 198 28 | SODIMM_38 = 79 29 | SODIMM_43 = 23 30 | SODIMM_44 = 73 31 | SODIMM_45 = 171 32 | SODIMM_46 = 39 33 | SODIMM_47 = 66 34 | SODIMM_48 = 41 35 | SODIMM_49 = 209 36 | SODIMM_50 = 43 37 | SODIMM_51 = 210 38 | SODIMM_52 = 44 39 | SODIMM_53 = 211 40 | SODIMM_54 = 45 41 | SODIMM_55 = 14 42 | SODIMM_56 = 11 43 | SODIMM_57 = 96 44 | SODIMM_58 = 35 45 | SODIMM_59 = 93 46 | SODIMM_60 = 34 47 | SODIMM_61 = 97 48 | SODIMM_62 = 40 49 | SODIMM_63 = 15 50 | SODIMM_64 = 47 51 | SODIMM_65 = 95 52 | SODIMM_66 = 46 53 | SODIMM_67 = 7 54 | SODIMM_68 = 75 55 | SODIMM_69 = 154 56 | SODIMM_70 = 33 57 | SODIMM_71 = 156 58 | SODIMM_72 = 37 59 | SODIMM_73 = 0 60 | SODIMM_74 = 42 61 | SODIMM_75 = 153 62 | SODIMM_76 = 32 63 | SODIMM_77 = 155 64 | SODIMM_78 = 36 65 | SODIMM_79 = 90 66 | SODIMM_80 = 38 67 | SODIMM_81 = 30 68 | SODIMM_82 = 76 69 | SODIMM_85 = 94 70 | SODIMM_86 = 27 71 | SODIMM_87 = 68 72 | SODIMM_88 = 24 73 | SODIMM_89 = 64 74 | SODIMM_90 = 25 75 | SODIMM_91 = 65 76 | SODIMM_92 = 28 77 | SODIMM_93 = 176 78 | SODIMM_94 = 31 79 | SODIMM_95 = 71 80 | SODIMM_96 = 152 81 | SODIMM_97 = 91 82 | SODIMM_98 = 29 83 | SODIMM_99 = 203 84 | SODIMM_100 = 189 85 | SODIMM_101 = 88 86 | SODIMM_102 = 190 87 | SODIMM_103 = 89 88 | SODIMM_104 = 191 89 | SODIMM_105 = 82 90 | SODIMM_106 = 84 91 | SODIMM_107 = 83 92 | SODIMM_110 = 162 93 | SODIMM_111 = 78 94 | SODIMM_112 = 163 95 | SODIMM_113 = 77 96 | SODIMM_114 = 164 97 | SODIMM_115 = 182 98 | SODIMM_116 = 165 99 | SODIMM_117 = 183 100 | SODIMM_118 = 166 101 | SODIMM_119 = 16 102 | SODIMM_120 = 124 103 | SODIMM_121 = 1 104 | SODIMM_122 = 125 105 | SODIMM_123 = 160 106 | SODIMM_124 = 126 107 | SODIMM_125 = 161 108 | SODIMM_126 = 72 109 | SODIMM_127 = 219 110 | SODIMM_128 = 74 111 | SODIMM_129 = 178 112 | SODIMM_130 = 67 113 | SODIMM_131 = 179 114 | SODIMM_132 = 70 115 | SODIMM_133 = 218 116 | SODIMM_134 = 188 117 | SODIMM_135 = 86 118 | SODIMM_136 = 98 119 | SODIMM_137 = 85 120 | SODIMM_138 = 186 121 | SODIMM_140 = 100 122 | SODIMM_142 = 184 123 | SODIMM_144 = 5 124 | SODIMM_146 = 4 125 | SODIMM_149 = 48 126 | SODIMM_150 = 80 127 | SODIMM_151 = 49 128 | SODIMM_152 = 81 129 | SODIMM_153 = 50 130 | SODIMM_154 = 10 131 | SODIMM_155 = 51 132 | SODIMM_156 = 202 133 | SODIMM_157 = 52 134 | SODIMM_158 = 109 135 | SODIMM_159 = 53 136 | SODIMM_160 = 108 137 | SODIMM_161 = 54 138 | SODIMM_162 = 110 139 | SODIMM_163 = 55 140 | SODIMM_164 = 204 141 | SODIMM_165 = 56 142 | SODIMM_166 = 212 143 | SODIMM_167 = 57 144 | SODIMM_168 = 213 145 | SODIMM_169 = 58 146 | SODIMM_170 = 214 147 | SODIMM_171 = 59 148 | SODIMM_172 = 215 149 | SODIMM_173 = 60 150 | SODIMM_174 = 104 151 | SODIMM_175 = 61 152 | SODIMM_176 = 105 153 | SODIMM_177 = 62 154 | SODIMM_178 = 106 155 | SODIMM_179 = 63 156 | SODIMM_180 = 107 157 | SODIMM_184 = 3 158 | SODIMM_186 = 2 159 | SODIMM_188 = 127 160 | SODIMM_190 = 159 161 | SODIMM_192 = 208 162 | SODIMM_194 = 21 163 | SODIMM_196 = 20 164 | SODIMM_14 = 111 165 | -------------------------------------------------------------------------------- /contrib/board_files/colibri-t30.conf: -------------------------------------------------------------------------------- 1 | # Toradex Colibri T30 Computer On Module. 2 | # http://developer.toradex.com/products/colibri-t30 3 | 4 | [board] 5 | dtfile = /proc/device-tree/model 6 | model = Toradex Colibri T30 on Colibri Evaluation Board 7 | 8 | [GPIO] 9 | ###Colibri T30 SODIMM number to GPIO number mapping 10 | 11 | SODIMM_19 = 19 12 | SODIMM_21 = 18 13 | SODIMM_22 = 239 14 | SODIMM_23 = 112 15 | SODIMM_24 = 230 16 | SODIMM_25 = 115 17 | SODIMM_27 = 116 18 | SODIMM_28 = 13 19 | SODIMM_29 = 119 20 | SODIMM_30 = 6 21 | SODIMM_31 = 118 22 | SODIMM_32 = 9 23 | SODIMM_33 = 114 24 | SODIMM_34 = 87 25 | SODIMM_35 = 113 26 | SODIMM_36 = 8 27 | SODIMM_37 = 117 28 | SODIMM_38 = 79 29 | SODIMM_43 = 23 30 | SODIMM_44 = 73 31 | SODIMM_45 = 169 32 | SODIMM_46 = 39 33 | SODIMM_47 = 224 34 | SODIMM_48 = 41 35 | SODIMM_49 = 217 36 | SODIMM_50 = 43 37 | SODIMM_51 = 218 38 | SODIMM_52 = 44 39 | SODIMM_53 = 219 40 | SODIMM_54 = 45 41 | SODIMM_55 = 14 42 | SODIMM_56 = 11 43 | SODIMM_57 = 96 44 | SODIMM_58 = 35 45 | SODIMM_59 = 12 46 | SODIMM_60 = 34 47 | SODIMM_61 = 97 48 | SODIMM_62 = 40 49 | SODIMM_63 = 15 50 | SODIMM_64 = 47 51 | SODIMM_65 = 238 52 | SODIMM_66 = 46 53 | SODIMM_67 = 7 54 | SODIMM_68 = 75 55 | SODIMM_69 = 237 56 | SODIMM_70 = 33 57 | SODIMM_71 = 170 58 | SODIMM_72 = 37 59 | SODIMM_73 = 144 60 | SODIMM_74 = 42 61 | SODIMM_75 = 181 62 | SODIMM_76 = 32 63 | SODIMM_77 = 226 64 | SODIMM_78 = 36 65 | SODIMM_79 = 197 66 | SODIMM_80 = 38 67 | SODIMM_81 = 17 68 | SODIMM_82 = 76 69 | SODIMM_85 = 171 70 | SODIMM_86 = 195 71 | SODIMM_87 = 68 72 | SODIMM_88 = 194 73 | SODIMM_89 = 64 74 | SODIMM_90 = 193 75 | SODIMM_91 = 65 76 | SODIMM_92 = 192 77 | SODIMM_93 = 176 78 | SODIMM_94 = 231 79 | SODIMM_95 = 71 80 | SODIMM_96 = 200 81 | SODIMM_97 = 196 82 | SODIMM_98 = 201 83 | SODIMM_99 = 203 84 | SODIMM_100 = 189 85 | SODIMM_101 = 199 86 | SODIMM_102 = 190 87 | SODIMM_103 = 198 88 | SODIMM_104 = 191 89 | SODIMM_105 = 82 90 | SODIMM_106 = 84 91 | SODIMM_107 = 83 92 | SODIMM_110 = 162 93 | SODIMM_111 = 78 94 | SODIMM_112 = 163 95 | SODIMM_113 = 77 96 | SODIMM_114 = 164 97 | SODIMM_115 = 182 98 | SODIMM_116 = 165 99 | SODIMM_117 = 183 100 | SODIMM_118 = 166 101 | SODIMM_119 = 16 102 | SODIMM_120 = 124 103 | SODIMM_121 = 1 104 | SODIMM_122 = 125 105 | SODIMM_123 = 160 106 | SODIMM_124 = 126 107 | SODIMM_125 = 161 108 | SODIMM_126 = 72 109 | SODIMM_127 = 158 110 | SODIMM_128 = 74 111 | SODIMM_129 = 178 112 | SODIMM_130 = 67 113 | SODIMM_131 = 179 114 | SODIMM_132 = 70 115 | SODIMM_133 = 157 116 | SODIMM_134 = 188 117 | SODIMM_135 = 86 118 | SODIMM_136 = 187 119 | SODIMM_137 = 85 120 | SODIMM_138 = 186 121 | SODIMM_140 = 185 122 | SODIMM_142 = 184 123 | SODIMM_144 = 5 124 | SODIMM_146 = 4 125 | SODIMM_149 = 48 126 | SODIMM_150 = 80 127 | SODIMM_151 = 49 128 | SODIMM_152 = 81 129 | SODIMM_153 = 50 130 | SODIMM_154 = 10 131 | SODIMM_155 = 51 132 | SODIMM_156 = 202 133 | SODIMM_157 = 52 134 | SODIMM_158 = 109 135 | SODIMM_159 = 53 136 | SODIMM_160 = 108 137 | SODIMM_161 = 54 138 | SODIMM_162 = 110 139 | SODIMM_163 = 55 140 | SODIMM_164 = 204 141 | SODIMM_165 = 56 142 | SODIMM_166 = 220 143 | SODIMM_167 = 57 144 | SODIMM_168 = 221 145 | SODIMM_169 = 58 146 | SODIMM_170 = 222 147 | SODIMM_171 = 59 148 | SODIMM_172 = 223 149 | SODIMM_173 = 60 150 | SODIMM_174 = 104 151 | SODIMM_175 = 61 152 | SODIMM_176 = 105 153 | SODIMM_177 = 62 154 | SODIMM_178 = 106 155 | SODIMM_179 = 63 156 | SODIMM_180 = 107 157 | SODIMM_184 = 3 158 | SODIMM_186 = 2 159 | SODIMM_188 = 127 160 | SODIMM_190 = 225 161 | SODIMM_192 = 216 162 | SODIMM_194 = 21 163 | SODIMM_196 = 20 164 | SODIMM_14 = 111 165 | SODIMM_15 = 172 166 | SODIMM_16 = 173 167 | SODIMM_23 = 175 168 | SODIMM_24 = 174 169 | -------------------------------------------------------------------------------- /contrib/board_files/colibri-vf50.conf: -------------------------------------------------------------------------------- 1 | # Toradex Colibri VF50 Computer On Module. 2 | # http://developer.toradex.com/products/colibri-vf50 3 | 4 | [board] 5 | dtfile = /proc/device-tree/model 6 | model = Toradex Colibri VF50 on Colibri Evaluation Board 7 | 8 | [GPIO] 9 | ### Colibri VF50 SODIMM number to GPIO number mapping 10 | 11 | SODIMM_19 = 27 12 | SODIMM_21 = 26 13 | SODIMM_22 = 104 14 | SODIMM_23 = 10 15 | SODIMM_24 = 25 16 | SODIMM_25 = 35 17 | SODIMM_27 = 34 18 | SODIMM_28 = 30 19 | SODIMM_29 = 21 20 | SODIMM_30 = 23 21 | SODIMM_31 = 11 22 | SODIMM_32 = 82 23 | SODIMM_33 = 33 24 | SODIMM_34 = 81 25 | SODIMM_35 = 32 26 | SODIMM_36 = 80 27 | SODIMM_37 = 20 28 | SODIMM_38 = 79 29 | SODIMM_43 = 42 30 | SODIMM_44 = 109 31 | SODIMM_45 = 41 32 | SODIMM_46 = 121 33 | SODIMM_47 = 14 34 | SODIMM_48 = 123 35 | SODIMM_49 = 17 36 | SODIMM_50 = 125 37 | SODIMM_51 = 18 38 | SODIMM_52 = 112 39 | SODIMM_53 = 19 40 | SODIMM_54 = 113 41 | SODIMM_55 = 39 42 | SODIMM_56 = 107 43 | SODIMM_57 = 116 44 | SODIMM_58 = 131 45 | SODIMM_59 = 22 46 | SODIMM_59# = 52 47 | SODIMM_60 = 130 48 | SODIMM_61 = 117 49 | SODIMM_62 = 122 50 | SODIMM_63 = 38 51 | SODIMM_64 = 115 52 | SODIMM_65 = 40 53 | SODIMM_66 = 114 54 | SODIMM_67 = 31 55 | SODIMM_67# = 51 56 | SODIMM_68 = 105 57 | SODIMM_69 = 64 58 | SODIMM_70 = 129 59 | SODIMM_71 = 45 60 | SODIMM_72 = 133 61 | SODIMM_73 = 43 62 | SODIMM_74 = 124 63 | SODIMM_75 = 91 64 | SODIMM_76 = 128 65 | SODIMM_77 = 44 66 | SODIMM_78 = 132 67 | SODIMM_79 = 49 68 | SODIMM_80 = 120 69 | SODIMM_81 = 29 70 | SODIMM_82 = 106 71 | SODIMM_85 = 53 72 | SODIMM_86 = 84 73 | SODIMM_88 = 87 74 | SODIMM_89 = 2 75 | SODIMM_90 = 85 76 | SODIMM_92 = 86 77 | SODIMM_93 = 98 78 | SODIMM_94 = 28 79 | SODIMM_95 = 103 80 | SODIMM_96 = 134 81 | SODIMM_97 = 50 82 | SODIMM_98 = 46 83 | SODIMM_99 = 65 84 | SODIMM_100 = 92 85 | SODIMM_101 = 47 86 | SODIMM_102 = 93 87 | SODIMM_103 = 48 88 | SODIMM_104 = 66 89 | SODIMM_105 = 96 90 | SODIMM_106 = 63 91 | SODIMM_107 = 67 92 | SODIMM_127 = 68 93 | SODIMM_129 = 83 94 | SODIMM_131 = 108 95 | SODIMM_133 = 88 96 | SODIMM_134 = 7 97 | SODIMM_135 = 89 98 | SODIMM_136 = 126 99 | SODIMM_137 = 102 100 | SODIMM_138 = 127 101 | SODIMM_140 = 118 102 | SODIMM_142 = 119 103 | SODIMM_144 = 110 104 | SODIMM_146 = 111 105 | SODIMM_184 = 69 106 | SODIMM_186 = 70 107 | SODIMM_188 = 90 108 | SODIMM_190 = 15 109 | SODIMM_192 = 16 110 | SODIMM_194 = 37 111 | SODIMM_196 = 36 112 | 113 | ### Colibri Evaluation Board location to GPIO mapping 114 | 115 | # (X9) 116 | X9_12 = 25 117 | X9_11 = 104 118 | X9_13 = 109 119 | X9_4 = 41 120 | X9_28 = 112 121 | X9_27 = 125 122 | X9_25 = 123 123 | X9_23 = 121 124 | X9_30 = 113 125 | X9_5 = 39 126 | X9_42 = 107 127 | X9_33 = 116 128 | X9_18 = 131 129 | X9_17 = 130 130 | X9_34 = 117 131 | X9_24 = 122 132 | X9_6 = 38 133 | X9_32 = 115 134 | X9_31 = 114 135 | X9_44 = 105 136 | X9_16 = 129 137 | X9_46 = 45 138 | X9_20 = 133 139 | X9_26 = 124 140 | X9_14 = 128 141 | X9_19 = 132 142 | X9_21 = 120 143 | X9_45 = 106 144 | X9_7 = 92 145 | X9_9 = 93 146 | X9_35 = 126 147 | X9_37 = 127 148 | X9_38 = 118 149 | X9_39 = 119 150 | X9_47 = 37 151 | X9_48 = 36 152 | X9_41 = 111 153 | X9_10 = 66 154 | X9_40 = 110 155 | 156 | # (X10) 157 | X10_2 = 27 158 | X10_3 = 26 159 | X10_4 = 10 160 | X10_5 = 35 161 | X10_6 = 34 162 | X10_27 = 30 163 | X10_7 = 21 164 | X10_28 = 23 165 | X10_9 = 11 166 | X10_30 = 82 167 | X10_19 = 33 168 | X10_14 = 81 169 | X10_11 = 32 170 | X10_16 = 80 171 | X10_12 = 20 172 | X10_17 = 79 173 | X10_18 = 42 174 | X10_19 = 14 175 | X10_23 = 17 176 | X10_24 = 18 177 | X10_25 = 19 178 | X10_26 = 22 179 | X10_26# = 52 180 | X10_30 = 31 181 | X10_30# = 51 182 | X10_31 = 43 183 | X10_32 = 84 184 | x10_33 = 87 185 | X10_34 = 85 186 | X10_35 = 86 187 | X10_37 = 96 188 | X10_42 = 68 189 | X10_38 = 67 190 | X10_47 = 83 191 | X10_48 = 108 192 | X10_41 = 88 193 | X10_39 = 63 194 | X10_40 = 89 195 | X10_49 = 102 196 | X10_20 = 15 197 | X10_21 = 16 198 | 199 | # (X22) 200 | X22_14 = 40 201 | X22_21 = 64 202 | X22_3 = 91 203 | X22_22 = 44 204 | X22_9 = 49 205 | X22_6 = 29 206 | X22_13 = 53 207 | X22_5 = 28 208 | X22_4 = 134 209 | X22_10 = 50 210 | X22_18 = 46 211 | X22_7 = 47 212 | X22_8 = 48 213 | 214 | # EX A 215 | EX_A_26 = 2 216 | EX_A_28 = 98 217 | EX_A_31 = 65 218 | EX_A_27 = 96 219 | EX_A_32 = 88 220 | EX_A_23 = 126 221 | EX_A_22 = 127 222 | EX_A_22 = 118 223 | EX_A_21 = 111 224 | EX_A_20 = 90 225 | 226 | # EX B 227 | EX_B_28 = 103 228 | EX_B_26 = 67 229 | EX_B_23 = 7 230 | EX_B_21 = 110 231 | EX_B_20 = 70 232 | 233 | # EX C 234 | EX_C_27 = 63 235 | EX_C_32 = 68 236 | EX_C_31 = 89 237 | EX_C_21 = 119 238 | EX_C_20 = 69 239 | 240 | ### Colibri Aster Carrier Board location to GPIO mapping 241 | 242 | # Extension Connector (X20) 243 | # This extension connector pinout is compatible with header pins available on 244 | # the Raspberry Pi, Type B+ board. 245 | # NOTE: Some of these functions might change depending on the Colibri module that is used. 246 | X20_32 = 30 247 | # Via R127 248 | x20_27 = 21 249 | X20_33 = 23 250 | X20_36 = 82 251 | X20_11 = 81 252 | X20_10 = 80 253 | # Via R128 254 | X20_28 = 20 255 | X20_8 = 79 256 | # Via R120 257 | X20_12 = 22 258 | X20_24 = 40 259 | # Via R122 260 | X20_35 = 31 261 | # Via R124 262 | X20_40 = 64 263 | X20_15 = 45 264 | X20_38 = 91 265 | X20_37 = 49 266 | X20_31 = 29 267 | x20_26 = 84 268 | X20_23 = 87 269 | X20_21 = 85 270 | X20_19 = 86 271 | X20_29 = 28 272 | X20_7 = 134 273 | X20_13 = 50 274 | X20_16 = 46 275 | # Via R125 276 | X20_40 = 92 277 | X20_22 = 47 278 | X20_18 = 48 279 | # Via R121 280 | X20_12 = 89 281 | # Via R123 282 | X20_35 = 90 283 | X20_3 = 37 284 | # Via R126 285 | #X20_12 = 37 286 | X20_5 = 36 287 | # Via R129 288 | #X20_28 = 36 289 | 290 | # Arduino Shield header: Digital I/OPins (X17) 291 | UNO_GPIO1 = 41 292 | UNO_GPIO2 = 31 293 | UNO_GPIO2# = 51 294 | UNO_GPIO3 = 88 295 | UNO_GPIO4 = 30 296 | UNO_GPIO5 = 23 297 | UNO_GPIO6 = 39 298 | UNO_GPIO7 = 38 299 | UNO_GPIO8 = 22 300 | UNO_GPIO8# = 52 301 | UNO_SPI_MOSI = 86 302 | UNO_SPI_MISO = 85 303 | UNO_SPI_SCK = 87 304 | UNO_I2C_SDA = 37 305 | UNO_I2C_SCL = 36 306 | 307 | ### Colibri Iris Carrier Board location to GPIO mapping 308 | 309 | # Extension Connctor (X16) 310 | X16_5 = 37 311 | X16_6 = 36 312 | X16_8 = 87 313 | X16_9 = 84 314 | X16_10 = 85 315 | X16_11 = 86 316 | X16_13 = 46 317 | X16_14 = 88 318 | X16_15 = 48 319 | X16_16 = 47 320 | X16_17 = 50 321 | X16_18 = 53 322 | X16_19 = 49 323 | X16_20 = 41 324 | X16_37 = 22 325 | X16_37# = 52 326 | X16_38 = 30 327 | X16_39 = 23 328 | X16_40 = 31 329 | X16_40# = 51 330 | 331 | ### Colibri Viola Carrier Board location to GPIO mapping 332 | 333 | # Extension Connector (X9) 334 | X9_42 = 30 335 | X9_16 = 41 336 | X9_17 = 39 337 | X9_41 = 22 338 | X9_18 = 38 339 | X9_44 = 31 340 | X9_44# = 51 341 | X9_15 = 49 342 | X9_14 = 53 343 | X9_13 = 50 344 | X9_9 = 46 345 | X9_12 = 47 346 | X9_11 = 48 347 | X9_10 = 88 348 | X9_8 = 89 349 | 350 | # (X10) 351 | X10_8 = 29 352 | X10_9 = 28 353 | X10_10 = 134 354 | X10_11 = 40 355 | X10_12 = 91 356 | -------------------------------------------------------------------------------- /contrib/board_files/colibri-vf61.conf: -------------------------------------------------------------------------------- 1 | # Toradex Colibri VF61 Computer On Module. 2 | # http://developer.toradex.com/products/colibri-vf61 3 | 4 | [board] 5 | dtfile = /proc/device-tree/model 6 | model = Toradex Colibri VF61 on Colibri Evaluation Board 7 | 8 | [GPIO] 9 | ### Colibri VF61 SODIMM number to GPIO number mapping 10 | 11 | SODIMM_19 = 27 12 | SODIMM_21 = 26 13 | SODIMM_22 = 104 14 | SODIMM_23 = 10 15 | SODIMM_24 = 25 16 | SODIMM_25 = 35 17 | SODIMM_27 = 34 18 | SODIMM_28 = 30 19 | SODIMM_29 = 21 20 | SODIMM_30 = 23 21 | SODIMM_31 = 11 22 | SODIMM_32 = 82 23 | SODIMM_33 = 33 24 | SODIMM_34 = 81 25 | SODIMM_35 = 32 26 | SODIMM_36 = 80 27 | SODIMM_37 = 20 28 | SODIMM_38 = 79 29 | SODIMM_43 = 42 30 | SODIMM_44 = 109 31 | SODIMM_45 = 41 32 | SODIMM_46 = 121 33 | SODIMM_47 = 14 34 | SODIMM_48 = 123 35 | SODIMM_49 = 17 36 | SODIMM_50 = 125 37 | SODIMM_51 = 18 38 | SODIMM_52 = 112 39 | SODIMM_53 = 19 40 | SODIMM_54 = 113 41 | SODIMM_55 = 39 42 | SODIMM_56 = 107 43 | SODIMM_57 = 116 44 | SODIMM_58 = 131 45 | SODIMM_59 = 22 46 | SODIMM_59# = 52 47 | SODIMM_60 = 130 48 | SODIMM_61 = 117 49 | SODIMM_62 = 122 50 | SODIMM_63 = 38 51 | SODIMM_64 = 115 52 | SODIMM_65 = 40 53 | SODIMM_66 = 114 54 | SODIMM_67 = 31 55 | SODIMM_67# = 51 56 | SODIMM_68 = 105 57 | SODIMM_69 = 64 58 | SODIMM_70 = 129 59 | SODIMM_71 = 45 60 | SODIMM_72 = 133 61 | SODIMM_73 = 43 62 | SODIMM_74 = 124 63 | SODIMM_75 = 91 64 | SODIMM_76 = 128 65 | SODIMM_77 = 44 66 | SODIMM_78 = 132 67 | SODIMM_79 = 49 68 | SODIMM_80 = 120 69 | SODIMM_81 = 29 70 | SODIMM_82 = 106 71 | SODIMM_85 = 53 72 | SODIMM_86 = 84 73 | SODIMM_88 = 87 74 | SODIMM_89 = 2 75 | SODIMM_90 = 85 76 | SODIMM_92 = 86 77 | SODIMM_93 = 98 78 | SODIMM_94 = 28 79 | SODIMM_95 = 103 80 | SODIMM_96 = 134 81 | SODIMM_97 = 50 82 | SODIMM_98 = 46 83 | SODIMM_99 = 65 84 | SODIMM_100 = 92 85 | SODIMM_101 = 47 86 | SODIMM_102 = 93 87 | SODIMM_103 = 48 88 | SODIMM_104 = 66 89 | SODIMM_105 = 96 90 | SODIMM_106 = 63 91 | SODIMM_107 = 67 92 | SODIMM_127 = 68 93 | SODIMM_129 = 83 94 | SODIMM_131 = 108 95 | SODIMM_133 = 88 96 | SODIMM_134 = 7 97 | SODIMM_135 = 89 98 | SODIMM_136 = 126 99 | SODIMM_137 = 102 100 | SODIMM_138 = 127 101 | SODIMM_140 = 118 102 | SODIMM_142 = 119 103 | SODIMM_144 = 110 104 | SODIMM_146 = 111 105 | SODIMM_184 = 69 106 | SODIMM_186 = 70 107 | SODIMM_188 = 90 108 | SODIMM_190 = 15 109 | SODIMM_192 = 16 110 | SODIMM_194 = 37 111 | SODIMM_196 = 36 112 | 113 | ### Colibri Evaluation Board location to GPIO mapping 114 | 115 | # (X9) 116 | X9_12 = 25 117 | X9_11 = 104 118 | X9_13 = 109 119 | X9_4 = 41 120 | X9_28 = 112 121 | X9_27 = 125 122 | X9_25 = 123 123 | X9_23 = 121 124 | X9_30 = 113 125 | X9_5 = 39 126 | X9_42 = 107 127 | X9_33 = 116 128 | X9_18 = 131 129 | X9_17 = 130 130 | X9_34 = 117 131 | X9_24 = 122 132 | X9_6 = 38 133 | X9_32 = 115 134 | X9_31 = 114 135 | X9_44 = 105 136 | X9_16 = 129 137 | X9_46 = 45 138 | X9_20 = 133 139 | X9_26 = 124 140 | X9_14 = 128 141 | X9_19 = 132 142 | X9_21 = 120 143 | X9_45 = 106 144 | X9_7 = 92 145 | X9_9 = 93 146 | X9_35 = 126 147 | X9_37 = 127 148 | X9_38 = 118 149 | X9_39 = 119 150 | X9_47 = 37 151 | X9_48 = 36 152 | X9_41 = 111 153 | X9_10 = 66 154 | X9_40 = 110 155 | 156 | # (X10) 157 | X10_2 = 27 158 | X10_3 = 26 159 | X10_4 = 10 160 | X10_5 = 35 161 | X10_6 = 34 162 | X10_27 = 30 163 | X10_7 = 21 164 | X10_28 = 23 165 | X10_9 = 11 166 | X10_30 = 82 167 | X10_19 = 33 168 | X10_14 = 81 169 | X10_11 = 32 170 | X10_16 = 80 171 | X10_12 = 20 172 | X10_17 = 79 173 | X10_18 = 42 174 | X10_19 = 14 175 | X10_23 = 17 176 | X10_24 = 18 177 | X10_25 = 19 178 | X10_26 = 22 179 | X10_26# = 52 180 | X10_30 = 31 181 | X10_30# = 51 182 | X10_31 = 43 183 | X10_32 = 84 184 | x10_33 = 87 185 | X10_34 = 85 186 | X10_35 = 86 187 | X10_37 = 96 188 | X10_42 = 68 189 | X10_38 = 67 190 | X10_47 = 83 191 | X10_48 = 108 192 | X10_41 = 88 193 | X10_39 = 63 194 | X10_40 = 89 195 | X10_49 = 102 196 | X10_20 = 15 197 | X10_21 = 16 198 | 199 | # (X22) 200 | X22_14 = 40 201 | X22_21 = 64 202 | X22_3 = 91 203 | X22_22 = 44 204 | X22_9 = 49 205 | X22_6 = 29 206 | X22_13 = 53 207 | X22_5 = 28 208 | X22_4 = 134 209 | X22_10 = 50 210 | X22_18 = 46 211 | X22_7 = 47 212 | X22_8 = 48 213 | 214 | # EX A 215 | EX_A_26 = 2 216 | EX_A_28 = 98 217 | EX_A_31 = 65 218 | EX_A_27 = 96 219 | EX_A_32 = 88 220 | EX_A_23 = 126 221 | EX_A_22 = 127 222 | EX_A_22 = 118 223 | EX_A_21 = 111 224 | EX_A_20 = 90 225 | 226 | # EX B 227 | EX_B_28 = 103 228 | EX_B_26 = 67 229 | EX_B_23 = 7 230 | EX_B_21 = 110 231 | EX_B_20 = 70 232 | 233 | # EX C 234 | EX_C_27 = 63 235 | EX_C_32 = 68 236 | EX_C_31 = 89 237 | EX_C_21 = 119 238 | EX_C_20 = 69 239 | 240 | ### Colibri Aster Carrier Board location to GPIO mapping 241 | 242 | # Extension Connector (X20) 243 | # This extension connector pinout is compatible with header pins available on 244 | # the Raspberry Pi, Type B+ board. 245 | # NOTE: Some of these functions might change depending on the Colibri module that is used. 246 | X20_32 = 30 247 | # Via R127 248 | x20_27 = 21 249 | X20_33 = 23 250 | X20_36 = 82 251 | X20_11 = 81 252 | X20_10 = 80 253 | # Via R128 254 | X20_28 = 20 255 | X20_8 = 79 256 | # Via R120 257 | X20_12 = 22 258 | X20_24 = 40 259 | # Via R122 260 | X20_35 = 31 261 | # Via R124 262 | X20_40 = 64 263 | X20_15 = 45 264 | X20_38 = 91 265 | X20_37 = 49 266 | X20_31 = 29 267 | x20_26 = 84 268 | X20_23 = 87 269 | X20_21 = 85 270 | X20_19 = 86 271 | X20_29 = 28 272 | X20_7 = 134 273 | X20_13 = 50 274 | X20_16 = 46 275 | # Via R125 276 | X20_40 = 92 277 | X20_22 = 47 278 | X20_18 = 48 279 | # Via R121 280 | X20_12 = 89 281 | # Via R123 282 | X20_35 = 90 283 | X20_3 = 37 284 | # Via R126 285 | #X20_12 = 37 286 | X20_5 = 36 287 | # Via R129 288 | #X20_28 = 36 289 | 290 | # Arduino Shield header: Digital I/OPins (X17) 291 | UNO_GPIO1 = 41 292 | UNO_GPIO2 = 31 293 | UNO_GPIO2# = 51 294 | UNO_GPIO3 = 88 295 | UNO_GPIO4 = 30 296 | UNO_GPIO5 = 23 297 | UNO_GPIO6 = 39 298 | UNO_GPIO7 = 38 299 | UNO_GPIO8 = 22 300 | UNO_GPIO8# = 52 301 | UNO_SPI_MOSI = 86 302 | UNO_SPI_MISO = 85 303 | UNO_SPI_SCK = 87 304 | UNO_I2C_SDA = 37 305 | UNO_I2C_SCL = 36 306 | 307 | ### Colibri Iris Carrier Board location to GPIO mapping 308 | 309 | # Extension Connctor (X16) 310 | X16_5 = 37 311 | X16_6 = 36 312 | X16_8 = 87 313 | X16_9 = 84 314 | X16_10 = 85 315 | X16_11 = 86 316 | X16_13 = 46 317 | X16_14 = 88 318 | X16_15 = 48 319 | X16_16 = 47 320 | X16_17 = 50 321 | X16_18 = 53 322 | X16_19 = 49 323 | X16_20 = 41 324 | X16_37 = 22 325 | X16_37# = 52 326 | X16_38 = 30 327 | X16_39 = 23 328 | X16_40 = 31 329 | X16_40# = 51 330 | 331 | ### Colibri Viola Carrier Board location to GPIO mapping 332 | 333 | # Extension Connector (X9) 334 | X9_42 = 30 335 | X9_16 = 41 336 | X9_17 = 39 337 | X9_41 = 22 338 | X9_18 = 38 339 | X9_44 = 31 340 | X9_44# = 51 341 | X9_15 = 49 342 | X9_14 = 53 343 | X9_13 = 50 344 | X9_9 = 46 345 | X9_12 = 47 346 | X9_11 = 48 347 | X9_10 = 88 348 | X9_8 = 89 349 | 350 | # (X10) 351 | X10_8 = 29 352 | X10_9 = 28 353 | X10_10 = 134 354 | X10_11 = 40 355 | X10_12 = 91 356 | -------------------------------------------------------------------------------- /contrib/board_files/dragonboard410c.conf: -------------------------------------------------------------------------------- 1 | [board] 2 | model = Qualcomm Technologies, Inc. APQ 8016 SBC 3 | 4 | [GPIO] 5 | # dragonboard 410c pin layout 6 | # 7 | GPIO-A = 36 8 | GPIO-B = 12 9 | GPIO-C = 13 10 | GPIO-D = 69 11 | GPIO-E = 115 12 | GPIO-F = 507 13 | GPIO-G = 24 14 | GPIO-H = 25 15 | GPIO-I = 35 16 | GPIO-J = 34 17 | GPIO-K = 28 18 | GPIO-L = 33 19 | 20 | # include mappings by pin number on board 21 | GPIO-23 = 36 22 | GPIO-24 = 12 23 | GPIO-25 = 13 24 | GPIO-26 = 69 25 | GPIO-27 = 115 26 | GPIO-28 = 507 27 | GPIO-29 = 24 28 | GPIO-30 = 25 29 | GPIO-31 = 35 30 | GPIO-32 = 34 31 | GPIO-33 = 28 32 | GPIO-34 = 33 33 | -------------------------------------------------------------------------------- /contrib/board_files/dragonboard820c.conf: -------------------------------------------------------------------------------- 1 | [board] 2 | model = Qualcomm Technologies, Inc. APQ 8096SGE SBC 3 | 4 | [GPIO] 5 | # dragonboard 820c pin layout 6 | # 7 | GPIO-A = 80 8 | GPIO-B = 29 9 | GPIO-C = 124 10 | GPIO-D = 24 11 | GPIO-E = 62 12 | GPIO-F = 507 13 | GPIO-G = 10 14 | GPIO-H = 8 15 | GPIO-I = 25 16 | GPIO-J = 26 17 | GPIO-K = 23 18 | GPIO-L = 133 19 | 20 | # include mappings by pin number on board 21 | GPIO-23 = 80 22 | GPIO-24 = 29 23 | GPIO-25 = 124 24 | GPIO-26 = 24 25 | GPIO-27 = 62 26 | GPIO-28 = 507 27 | GPIO-29 = 10 28 | GPIO-30 = 8 29 | GPIO-31 = 25 30 | GPIO-32 = 26 31 | GPIO-33 = 23 32 | GPIO-34 = 133 33 | -------------------------------------------------------------------------------- /contrib/board_files/example.conf: -------------------------------------------------------------------------------- 1 | # A board config file consists of two required sections, the "board" and "GPIO" 2 | # Lines starting with "#" are ignored 3 | 4 | [board] 5 | # When attempting an automatic configuration probe at library runtime, the 6 | # dtfile option contains the path to the file which will be read and it's 7 | # contents compared against the 'model' option. Change this value if you want 8 | # your 'model' option to be compared to a different file. 9 | # dtfile = /proc/device-tree/model 10 | 11 | # The model value is compared to the contents of the file path in 'dtfile'. If 12 | # the white space trimmed 'model' option, is equal to the contents of the 13 | # whitespace trimmed 'dtfile' then the automatic probe will succed and this 14 | # board config file selected. 15 | model = Example Board Name 16 | 17 | [GPIO] 18 | # Provide a list of board pin "names" to GPIO IDs on the chip. 19 | # P9_42 = 7 20 | 21 | # You can list a single GPIO ID more than once if you needed aliases. ie: 22 | PIN_23 = 12 23 | SPI_CS = 12 24 | -------------------------------------------------------------------------------- /contrib/board_files/hikey.conf: -------------------------------------------------------------------------------- 1 | [board] 2 | model = HiKey Development Board 3 | 4 | [GPIO] 5 | # hikey pin layout 6 | # 7 | GPIO-A = 488 8 | GPIO-B = 489 9 | GPIO-C = 490 10 | GPIO-D = 491 11 | GPIO-E = 492 12 | GPIO-F = 415 13 | GPIO-G = 463 14 | GPIO-H = 495 15 | GPIO-I = 426 16 | GPIO-J = 433 17 | GPIO-K = 427 18 | GPIO-L = 434 19 | 20 | # include mappings by pin number on board 21 | GPIO-23 = 488 22 | GPIO-24 = 489 23 | GPIO-25 = 490 24 | GPIO-26 = 491 25 | GPIO-27 = 492 26 | GPIO-28 = 415 27 | GPIO-29 = 463 28 | GPIO-30 = 495 29 | GPIO-31 = 426 30 | GPIO-32 = 433 31 | GPIO-33 = 427 32 | GPIO-34 = 434 33 | -------------------------------------------------------------------------------- /contrib/board_files/odroid_c2.conf: -------------------------------------------------------------------------------- 1 | [board] 2 | model = Hardkernel ODROID-C2 3 | # http://odroid.com/dokuwiki/doku.php?id=en:c2_hardware 4 | 5 | [GPIO] 6 | J2_3 = 205 7 | J2_5 = 206 8 | J2_7 = 249 9 | J2_8 = 240 10 | J2_10 = 241 11 | J2_11 = 247 12 | J2_12 = 238 13 | J2_13 = 239 14 | J2_15 = 237 15 | J2_16 = 236 16 | J2_18 = 233 17 | J2_19 = 235 18 | J2_21 = 232 19 | J2_22 = 231 20 | J2_23 = 230 21 | J2_24 = 229 22 | J2_26 = 225 23 | J2_27 = 207 24 | J2_28 = 208 25 | J2_29 = 228 26 | J2_31 = 219 27 | J2_32 = 224 28 | J2_33 = 234 29 | J2_35 = 214 30 | J2_36 = 218 31 | -------------------------------------------------------------------------------- /contrib/board_files/opos6ul_dev.conf: -------------------------------------------------------------------------------- 1 | [board] 2 | model = opos6ul_dev 3 | 4 | [GPIO] 5 | 6 | # Led/button, don't forget to delete led/button declaration in DTS 7 | USER_LED = 68 8 | USER_SWITCH = 43 9 | 10 | # Raspberry Pi extension (J3) 11 | J3_3 = 31 12 | J3_5 = 30 13 | J3_7 = 9 14 | J3_8 = 20 15 | J3_10 = 21 16 | J3_11 = 24 17 | J3_12 = 8 18 | J3_13 = 25 19 | J3_15 = 96 20 | J3_16 = 18 21 | J3_18 = 19 22 | J3_19 = 103 23 | J3_21 = 104 24 | J3_22 = 97 25 | J3_23 = 102 26 | J3_24 = 105 27 | J3_26 = 99 28 | J3_27 = 29 29 | J3_28 = 28 30 | J3_29 = 132 31 | J3_31 = 133 32 | J3_32 = 128 33 | J3_33 = 134 34 | J3_35 = 135 35 | J3_36 = 129 36 | J3_37 = 136 37 | J3_38 = 130 38 | J3_40 = 131 39 | 40 | # CMOS Sensor Interface (J13) 41 | J13_3 = 30 42 | J13_4 = 31 43 | J13_5 = 114 44 | J13_6 = 113 45 | J13_7 = 116 46 | J13_8 = 115 47 | J13_9 = 117 48 | J13_10 = 118 49 | J13_11 = 119 50 | J13_12 = 120 51 | J13_13 = 121 52 | J13_14 = 122 53 | J13_15 = 123 54 | J13_16 = 124 55 | J13_17 = 100 56 | J13_18 = 101 57 | 58 | # TFT CMOS Interface (J21), must be deleted in DTS before compile 59 | J21_6 = 106 60 | J21_8 = 65 61 | J21_10 = 66 62 | J21_12 = 67 63 | J21_31 = 69 64 | J21_13 = 70 65 | J21_16 = 71 66 | J21_15 = 72 67 | J21_18 = 73 68 | J21_17 = 74 69 | J21_20 = 75 70 | J21_19 = 76 71 | J21_22 = 77 72 | J21_21 = 78 73 | J21_24 = 79 74 | J21_23 = 80 75 | J21_32 = 81 76 | J21_26 = 82 77 | J21_25 = 83 78 | J21_28 = 84 79 | J21_27 = 85 80 | J21_29 = 86 81 | -------------------------------------------------------------------------------- /contrib/board_files/pocketbeagle.conf: -------------------------------------------------------------------------------- 1 | [board] 2 | model = TI AM335x PocketBeagle 3 | 4 | [GPIO] 5 | # 6 | #P2 Header Pins 7 | P2_1 = 50 8 | P2_2 = 59 9 | P2_3 = 23 10 | P2_4 = 58 11 | P2_5 = 30 12 | P2_6 = 57 13 | P2_7 = 31 14 | P2_8 = 60 15 | P2_9 = 15 16 | P2_10 = 52 17 | P2_11 = 14 18 | P2_17 = 65 19 | P2_18 = 47 20 | P2_19 = 27 21 | P2_20 = 64 22 | P2_22 = 46 23 | P2_25 = 41 24 | P2_27 = 40 25 | P2_28 = 116 26 | P2_29 = 7 27 | P2_30 = 113 28 | P2_32 = 112 29 | P2_33 = 45 30 | P2_31 = 19 31 | P2_34 = 115 32 | P2_35 = 86 33 | #P1 Header Pins 34 | P1_2 = 87 35 | P1_3 = 109 36 | P1_4 = 89 37 | P1_6 = 5 38 | P1_8 = 2 39 | P1_10 = 3 40 | P1_12 = 4 41 | P1_20 = 20 42 | P1_26 = 12 43 | P1_28 = 13 44 | P1_29 = 117 45 | P1_30 = 43 46 | P1_31 = 114 47 | P1_32 = 42 48 | P1_33 = 111 49 | P1_34 = 26 50 | P1_35 = 88 51 | P1_36 = 110 52 | 53 | GPIO1_21 = 53 54 | LED_USR0 = 53 55 | GPIO1_22 = 54 56 | LED_USR1 = 54 57 | GPIO1_23 = 55 58 | LED_USR2 = 55 59 | GPIO1_24 = 56 60 | LED_USR3 = 56 61 | GPIO2_8 = 72 62 | LCD_DATA2 = 72 63 | -------------------------------------------------------------------------------- /contrib/board_files/raspberrypi3b-rev1v2.conf: -------------------------------------------------------------------------------- 1 | # Raspberry Pi 3 Model B Rev 1.2 2 | # https://www.raspberrypi.org/products/raspberry-pi-3-model-b/ 3 | 4 | [board] 5 | dtfile = /proc/device-tree/model 6 | model=Raspberry Pi 3 Model B Rev 1.2 7 | 8 | [GPIO] 9 | P1_03 = 2 10 | P1_05 = 3 11 | P1_07 = 4 12 | P1_08 = 14 13 | P1_10 = 15 14 | P1_11 = 17 15 | P1_12 = 18 16 | P1_13 = 21 17 | P1_15 = 22 18 | P1_16 = 23 19 | P1_18 = 24 20 | P1_19 = 10 21 | P1_21 = 9 22 | P1_22 = 25 23 | P1_23 = 11 24 | P1_24 = 8 25 | P1_26 = 7 26 | P1_27 = 0 27 | P1_28 = 1 28 | P1_29 = 5 29 | P1_31 = 6 30 | P1_32 = 12 31 | P1_33 = 13 32 | P1_35 = 19 33 | P1_36 = 16 34 | P1_37 = 26 35 | P1_38 = 20 36 | P1_40 = 21 37 | -------------------------------------------------------------------------------- /contrib/board_files/raspberrypi3b-rev1v3.conf: -------------------------------------------------------------------------------- 1 | # Raspberry Pi 3 Model B Rev 1.3 2 | # https://www.raspberrypi.org/products/raspberry-pi-3-model-b/ 3 | 4 | [board] 5 | dtfile = /proc/device-tree/model 6 | model=Raspberry Pi 3 Model B Rev 1.3 7 | 8 | [GPIO] 9 | P1_03 = 2 10 | P1_05 = 3 11 | P1_07 = 4 12 | P1_08 = 14 13 | P1_10 = 15 14 | P1_11 = 17 15 | P1_12 = 18 16 | P1_13 = 21 17 | P1_15 = 22 18 | P1_16 = 23 19 | P1_18 = 24 20 | P1_19 = 10 21 | P1_21 = 9 22 | P1_22 = 25 23 | P1_23 = 11 24 | P1_24 = 8 25 | P1_26 = 7 26 | P1_27 = 0 27 | P1_28 = 1 28 | P1_29 = 5 29 | P1_31 = 6 30 | P1_32 = 12 31 | P1_33 = 13 32 | P1_35 = 19 33 | P1_36 = 16 34 | P1_37 = 26 35 | P1_38 = 20 36 | P1_40 = 21 37 | -------------------------------------------------------------------------------- /contrib/board_files/sd600_eval.conf: -------------------------------------------------------------------------------- 1 | [board] 2 | model = Arrow Electronics, APQ8064 DB600c 3 | 4 | [GPIO] 5 | # SD 600eval pin layout 6 | # 7 | GPIO-A = 35 8 | GPIO-B = 33 9 | GPIO-C = 55 10 | GPIO-D = 56 11 | GPIO-E = 29 12 | GPIO-F = 493 13 | GPIO-G = 0 14 | # GPIO-H is currently non-functional 15 | GPIO-I = 28 16 | GPIO-J = 30 17 | GPIO-K = 34 18 | GPIO-L = 31 19 | 20 | # include mappings by pin number on board 21 | GPIO-23 = 35 22 | GPIO-24 = 33 23 | GPIO-25 = 55 24 | GPIO-26 = 56 25 | GPIO-27 = 29 26 | GPIO-28 = 493 27 | GPIO-29 = 0 28 | # GPIO-30 is currently non-functional 29 | GPIO-31 = 28 30 | GPIO-32 = 30 31 | GPIO-33 = 34 32 | GPIO-34 = 31 33 | -------------------------------------------------------------------------------- /contrib/board_files/tinkerboard_rk3288.conf: -------------------------------------------------------------------------------- 1 | [board] 2 | model = Rockchip RK3288 Asus Tinker Board 3 | 4 | [GPIO] 5 | # rk3288 pin layout 6 | # https://github.com/TinkerBoard/gpio_lib_python/blob/sbc/tinkerboard/python/source/RKIO.h 7 | # 8 | GPIO0_C1 = 17 9 | 10 | GPIO5_B0 = 160 11 | GPIO5_B1 = 161 12 | GPIO5_B2 = 162 13 | GPIO5_B3 = 163 14 | GPIO5_B4 = 164 15 | GPIO5_B5 = 165 16 | GPIO5_B6 = 166 17 | GPIO5_B7 = 167 18 | GPIO5_C0 = 168 19 | GPIO5_C1 = 169 20 | GPIO5_C2 = 170 21 | GPIO5_C3 = 171 22 | 23 | GPIO6_A0 = 184 24 | GPIO6_A1 = 185 25 | GPIO6_A3 = 187 26 | GPIO6_A4 = 188 27 | 28 | GPIO7_A0 = 216 29 | GPIO7_A7 = 223 30 | GPIO7_B0 = 224 31 | GPIO7_B1 = 225 32 | GPIO7_B2 = 226 33 | GPIO7_C1 = 233 34 | GPIO7_C2 = 234 35 | GPIO7_C6 = 238 36 | GPIO7_C7 = 239 37 | 38 | GPIO8_A3 = 251 39 | GPIO8_A4 = 252 40 | GPIO8_A5 = 253 41 | GPIO8_A6 = 254 42 | GPIO8_A7 = 255 43 | GPIO8_B0 = 256 44 | GPIO8_B1 = 257 45 | 46 | # board pin mapping 47 | PIN3 = 252 48 | PIN5 = 253 49 | PIN7 = 17 50 | PIN8 = 161 51 | PIN10 = 160 52 | PIN11 = 164 53 | PIN12 = 184 54 | PIN13 = 166 55 | PIN15 = 167 56 | PIN16 = 162 57 | PIN18 = 163 58 | PIN19 = 257 59 | PIN21 = 256 60 | PIN22 = 171 61 | PIN23 = 254 62 | PIN24 = 255 63 | PIN27 = 233 64 | PIN28 = 234 65 | PIN29 = 165 66 | PIN31 = 168 67 | PIN32 = 239 68 | PIN33 = 238 69 | PIN35 = 185 70 | PIN36 = 223 71 | PIN37 = 224 72 | PIN38 = 187 73 | PIN40 = 188 74 | -------------------------------------------------------------------------------- /lib/Makefile.am: -------------------------------------------------------------------------------- 1 | lib_LTLIBRARIES = libsoc.la 2 | include_HEADERS = include/libsoc_gpio.h \ 3 | include/libsoc_spi.h \ 4 | include/libsoc_i2c.h \ 5 | include/libsoc_pwm.h \ 6 | include/libsoc_board.h \ 7 | include/libsoc_conffile.h \ 8 | include/libsoc_debug.h 9 | 10 | libsoc_la_SOURCES = gpio.c \ 11 | spi.c \ 12 | file.c \ 13 | i2c.c \ 14 | pwm.c \ 15 | board.c \ 16 | conffile.c \ 17 | debug.c 18 | 19 | libsoc_la_CPPFLAGS = -I${top_srcdir}/lib/include 20 | 21 | ## interface : source : age 22 | 23 | libsoc_la_LDFLAGS = -version-info 6:2:4 24 | AM_CFLAGS = -DDATA_DIR=\"$(DESTDIR)$(pkgdatadir)\" -DLIBSOC_CONF=\"@sysconfdir@/libsoc.conf\" 25 | -------------------------------------------------------------------------------- /lib/board.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: LGPL-2.1-only */ 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "libsoc_board.h" 10 | #include "libsoc_debug.h" 11 | #include "libsoc_file.h" 12 | 13 | static const char * 14 | _get_conf_file() 15 | { 16 | const char *name = getenv("LIBSOC_CONF"); 17 | if (name == NULL) 18 | name = LIBSOC_CONF; 19 | return name; 20 | } 21 | 22 | static int 23 | _probe_config(conffile *conf) 24 | { 25 | const char *dtfile = conffile_get(conf, "board", "dtfile", "/proc/device-tree/model"); 26 | const char *match = conffile_get(conf, "board", "model", NULL); 27 | if (match) 28 | { 29 | char *probed = file_read_contents(dtfile); 30 | if (probed) 31 | { 32 | int rc = strcmp(probed, match); 33 | free(probed); 34 | return !rc; 35 | } 36 | } 37 | else 38 | { 39 | libsoc_debug(__func__, "No 'model' value found in 'board' section"); 40 | } 41 | return 0; 42 | } 43 | 44 | static board_config * 45 | _probe() 46 | { 47 | board_config *bc = NULL; 48 | conffile *conf = NULL; 49 | const char *confs_dir = DATA_DIR; 50 | char tmp[PATH_MAX]; 51 | DIR *dirp; 52 | struct dirent *dp; 53 | 54 | if ((dirp = opendir(confs_dir)) != NULL) 55 | { 56 | do 57 | { 58 | if ((dp = readdir(dirp)) != NULL) 59 | { 60 | char *ext = strrchr(dp->d_name, '.'); 61 | if (ext && !strcmp(ext, ".conf")) 62 | { 63 | strcpy(tmp, confs_dir); 64 | strcat(tmp, "/"); 65 | strcat(tmp, dp->d_name); 66 | conf = conffile_load(tmp); 67 | if (conf) 68 | { 69 | libsoc_debug(__func__, "probing %s for board support", tmp); 70 | if(_probe_config(conf)) 71 | { 72 | libsoc_debug(__func__, "probing match for %s", tmp); 73 | bc = calloc(1, sizeof(board_config)); 74 | bc->conf = conf; 75 | } 76 | else 77 | conffile_free(conf); 78 | } 79 | } 80 | } 81 | } while (dp != NULL && bc == NULL); 82 | closedir(dirp); 83 | } 84 | else 85 | { 86 | libsoc_warn("Unable to read directory: %s", confs_dir); 87 | } 88 | return bc; 89 | } 90 | 91 | board_config* 92 | libsoc_board_init() 93 | { 94 | board_config *bc = NULL; 95 | const char *conf = _get_conf_file(); 96 | 97 | if (!access(conf, F_OK)) 98 | { 99 | bc = calloc(sizeof(board_config), 1); 100 | bc->conf = conffile_load(conf); 101 | if (!bc->conf) 102 | { 103 | free(bc); 104 | bc = NULL; 105 | } 106 | } 107 | else 108 | { 109 | bc = _probe(); 110 | if (!bc) 111 | libsoc_warn("Board config(%s) does not exist and could not be probed", conf); 112 | } 113 | 114 | return bc; 115 | } 116 | 117 | void 118 | libsoc_board_free(board_config *config) 119 | { 120 | if (config) 121 | { 122 | conffile_free(config->conf); 123 | free(config); 124 | } 125 | } 126 | 127 | int 128 | libsoc_board_gpio_id(board_config *config, const char* pin) 129 | { 130 | return conffile_get_int(config->conf, "GPIO", pin, -1); 131 | } 132 | -------------------------------------------------------------------------------- /lib/conffile.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: LGPL-2.1-only */ 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "libsoc_debug.h" 11 | #include "libsoc_conffile.h" 12 | 13 | static char * 14 | trim(char *buf) 15 | { 16 | size_t len = strlen(buf); 17 | while (isspace(buf[--len])) 18 | buf[len] = '\0'; 19 | while (isspace(*buf)) 20 | buf++; 21 | return buf; 22 | } 23 | 24 | static keyval* 25 | _create_keyval(const char *path, char *line) 26 | { 27 | keyval *kv; 28 | char *key, *val, *save; 29 | key = strtok_r(line, "=", &save); 30 | val = strtok_r(NULL, "\n", &save); 31 | if (!val) 32 | { 33 | libsoc_warn("Invalid key = value in %s:\n%s\n", path, line); 34 | return NULL; 35 | } 36 | key = trim(key); 37 | val = trim(val); 38 | kv = calloc(1, sizeof(keyval)); 39 | kv->key = strdup(key); 40 | kv->val = strdup(val); 41 | return kv; 42 | } 43 | 44 | conffile * 45 | conffile_load(const char *path) 46 | { 47 | int rc; 48 | FILE *fp; 49 | char line[256]; 50 | conffile *conf = calloc(1, sizeof(conffile)); 51 | section *stmp = NULL; 52 | keyval *ktmp = NULL; 53 | 54 | fp = fopen (path, "r"); 55 | if (fp) 56 | { 57 | while(fgets(line, sizeof(line), fp)) 58 | { 59 | if (*line == '#' || *line == '\0' || *line == '\n') 60 | continue; 61 | if (line[0] == '[') 62 | { 63 | // new section 64 | stmp = calloc(1, sizeof(section)); 65 | stmp->next = conf->sections; 66 | conf->sections = stmp; 67 | 68 | rc = strlen(line); 69 | if (line[rc-2] != ']' || (rc-2) > sizeof(stmp->name)) 70 | { 71 | libsoc_warn("Invalid section line in %s:\n%s\n", path, line); 72 | goto cleanup; 73 | } 74 | line[rc-2] = '\0'; 75 | strcpy(stmp->name, trim(&line[1])); 76 | } 77 | else 78 | { 79 | if (!conf->sections) 80 | { 81 | libsoc_warn("Section must be declared in %s before line: %s\n", 82 | path, line); 83 | } 84 | ktmp = _create_keyval(path, line); 85 | if (ktmp) 86 | { 87 | ktmp->next = conf->sections->settings; 88 | conf->sections->settings = ktmp; 89 | } 90 | else 91 | { 92 | goto cleanup; 93 | } 94 | } 95 | } 96 | fclose(fp); 97 | } 98 | else 99 | { 100 | libsoc_warn("Unable to open board config: %s\n", path); 101 | } 102 | 103 | return conf; 104 | 105 | cleanup: 106 | if (fp) 107 | fclose(fp); 108 | conffile_free(conf); 109 | return NULL; 110 | } 111 | 112 | void conffile_free(conffile *conf) 113 | { 114 | section *sptr, *stmp; 115 | keyval *kptr, *ktmp; 116 | 117 | if (!conf) 118 | return; 119 | 120 | sptr = conf->sections; 121 | while (sptr) 122 | { 123 | kptr = sptr->settings; 124 | while (kptr) 125 | { 126 | ktmp = kptr->next; 127 | free(kptr->key); 128 | free(kptr->val); 129 | free(kptr); 130 | kptr = ktmp; 131 | } 132 | stmp = sptr->next; 133 | free(sptr); 134 | sptr = stmp; 135 | } 136 | } 137 | 138 | const char* 139 | conffile_get(conffile *conf, const char *sectname, const char *key, const char *defval) 140 | { 141 | section *s = conf->sections; 142 | while(s) 143 | { 144 | if (!strcmp(s->name, sectname)) 145 | { 146 | keyval *kv = s->settings; 147 | while(kv) 148 | { 149 | if (!strcmp(kv->key, key)) 150 | return kv->val; 151 | kv = kv->next; 152 | } 153 | return defval; 154 | } 155 | s = s->next; 156 | } 157 | return defval; 158 | } 159 | 160 | 161 | int 162 | conffile_get_int(conffile *conf, const char *sectname, const char *key, int defval) 163 | { 164 | long val = defval; 165 | const char *strval = conffile_get(conf, sectname, key, NULL); 166 | if (strval) 167 | { 168 | char *endptr; 169 | errno = 0; 170 | val = strtol(strval, &endptr, 10); 171 | if ((errno == ERANGE && (val == LONG_MAX || val == LONG_MIN)) 172 | || (errno != 0 && val == 0) || endptr == strval || *endptr != '\0' 173 | || val > INT_MAX) 174 | { 175 | libsoc_warn("Invalid number: %s\n", strval); 176 | val = defval; 177 | } 178 | } 179 | return val; 180 | } 181 | -------------------------------------------------------------------------------- /lib/debug.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: LGPL-2.1-only */ 2 | 3 | #include 4 | #include 5 | 6 | int debug = 0; 7 | 8 | void 9 | libsoc_debug (const char *func, char *format, ...) 10 | { 11 | #ifdef DEBUG 12 | 13 | if (debug) 14 | { 15 | va_list args; 16 | 17 | fprintf (stderr, "libsoc-debug: "); 18 | 19 | va_start (args, format); 20 | vfprintf (stderr, format, args); 21 | va_end (args); 22 | 23 | fprintf (stderr, " (%s)", func); 24 | 25 | fprintf (stderr, "\n"); 26 | } 27 | #endif 28 | } 29 | 30 | void 31 | libsoc_warn (const char *format, ...) 32 | { 33 | va_list args; 34 | 35 | fprintf (stderr, "libsoc-warn: "); 36 | 37 | va_start (args, format); 38 | vfprintf (stderr, format, args); 39 | va_end (args); 40 | 41 | fprintf (stderr, "\n"); 42 | } 43 | 44 | void 45 | libsoc_set_debug (int level) 46 | { 47 | #ifdef DEBUG 48 | 49 | if (level) 50 | { 51 | debug = 1; 52 | libsoc_debug (__func__, "debug enabled"); 53 | } 54 | else 55 | { 56 | libsoc_debug (__func__, "debug disabled"); 57 | debug = 0; 58 | } 59 | 60 | #else 61 | 62 | printf ("libsoc-gpio: warning debug support missing!\n"); 63 | 64 | #endif 65 | } 66 | 67 | int 68 | libsoc_get_debug () 69 | { 70 | #ifdef DEBUG 71 | 72 | return debug; 73 | 74 | #else 75 | 76 | printf ("libsoc-debug: warning debug support missing!\n"); 77 | 78 | #endif 79 | } 80 | -------------------------------------------------------------------------------- /lib/file.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: LGPL-2.1-only */ 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | int file_open(const char *path, int flags) 10 | { 11 | int fd = open(path, flags); 12 | 13 | if (fd < 0) 14 | { 15 | perror("libsoc-file-debug"); 16 | return -1; 17 | } 18 | 19 | return fd; 20 | } 21 | 22 | int file_write(int fd, const char *str, int len) 23 | { 24 | int ret_len = write(fd, str, len); 25 | 26 | if (ret_len < 0) 27 | { 28 | perror("libsoc-file-debug"); 29 | return -1; 30 | } 31 | 32 | return ret_len; 33 | } 34 | 35 | int file_read(int fd, void *buf, int count) 36 | { 37 | lseek (fd, 0, SEEK_SET); 38 | int ret = read(fd, buf, count); 39 | 40 | if (ret < 0) 41 | { 42 | perror("libsoc-file-debug"); 43 | return -1; 44 | } 45 | 46 | return ret; 47 | } 48 | 49 | int file_valid(char *path) 50 | { 51 | if (access(path, F_OK) == 0) 52 | { 53 | return 1; 54 | } 55 | 56 | return 0; 57 | } 58 | 59 | int file_close(int fd) 60 | { 61 | if (close(fd) < 0) 62 | { 63 | perror ("libsoc-file-debug"); 64 | return -1; 65 | } 66 | 67 | return 0; 68 | } 69 | 70 | #define INT_STR_BUF 20 71 | 72 | int file_read_int_fd(int fd, int *tmp) 73 | { 74 | char buf[INT_STR_BUF]; 75 | 76 | if (file_read(fd, buf, INT_STR_BUF) < 0) 77 | { 78 | return EXIT_FAILURE; 79 | } 80 | 81 | *tmp = atoi(buf); 82 | 83 | return EXIT_SUCCESS; 84 | } 85 | 86 | int file_read_int_path(char *path, int *tmp) 87 | { 88 | int fd, ret; 89 | 90 | fd = file_open(path, O_SYNC | O_RDONLY); 91 | 92 | if (fd < 0) 93 | { 94 | return EXIT_FAILURE; 95 | } 96 | 97 | ret = file_read_int_fd(fd, tmp); 98 | 99 | if (file_close(fd) < 0 || ret == EXIT_FAILURE) 100 | { 101 | return EXIT_FAILURE; 102 | } 103 | 104 | return EXIT_SUCCESS; 105 | } 106 | 107 | int file_write_int_fd(int fd, int val) 108 | { 109 | char buf[INT_STR_BUF]; 110 | 111 | sprintf(buf, "%d", val); 112 | 113 | if (file_write(fd, buf, INT_STR_BUF) < 0) 114 | { 115 | return EXIT_FAILURE; 116 | } 117 | 118 | return EXIT_SUCCESS; 119 | } 120 | 121 | int file_write_int_path(char *path, int val) 122 | { 123 | int fd, ret; 124 | 125 | fd = file_open(path, O_SYNC | O_WRONLY); 126 | 127 | if (fd < 0) 128 | { 129 | return EXIT_FAILURE; 130 | } 131 | 132 | ret = file_write_int_fd(fd, val); 133 | 134 | if (file_close(fd) < 0 || ret == EXIT_FAILURE) 135 | { 136 | return EXIT_FAILURE; 137 | } 138 | 139 | return EXIT_SUCCESS; 140 | } 141 | 142 | int file_read_str(char *path, char *tmp, int buf_len) 143 | { 144 | int fd; 145 | 146 | fd = file_open(path, O_SYNC | O_RDONLY); 147 | 148 | if (fd < 0) 149 | { 150 | return EXIT_FAILURE; 151 | } 152 | 153 | if (file_read(fd, tmp, buf_len) < 0) 154 | { 155 | return EXIT_FAILURE; 156 | } 157 | 158 | if (file_close(fd) < 0) 159 | { 160 | return EXIT_FAILURE; 161 | } 162 | 163 | return EXIT_SUCCESS; 164 | } 165 | 166 | int file_write_str(char *path, char* buf, int len) 167 | { 168 | int fd; 169 | 170 | fd = file_open(path, O_SYNC | O_WRONLY); 171 | 172 | if (fd < 0) 173 | { 174 | return EXIT_FAILURE; 175 | } 176 | 177 | if (file_write(fd, buf, len) < 0) 178 | { 179 | return EXIT_FAILURE; 180 | } 181 | 182 | if (file_close(fd) < 0) 183 | { 184 | return EXIT_FAILURE; 185 | } 186 | 187 | return EXIT_SUCCESS; 188 | } 189 | 190 | char* file_read_contents(const char *path) 191 | { 192 | int fd; 193 | struct stat st; 194 | char *buf; 195 | 196 | if (stat(path, &st)) 197 | { 198 | perror("libsoc-file-debug"); 199 | return NULL; 200 | } 201 | 202 | fd = file_open(path, O_RDONLY); 203 | if (fd < 0) 204 | return NULL; 205 | 206 | buf = malloc(st.st_size); 207 | if (buf) 208 | { 209 | if (file_read(fd, buf, st.st_size) != st.st_size) 210 | { 211 | free(buf); 212 | return NULL; 213 | } 214 | } 215 | return buf; 216 | } 217 | -------------------------------------------------------------------------------- /lib/gpio.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: LGPL-2.1-only */ 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include "libsoc_file.h" 14 | #include "libsoc_debug.h" 15 | #include "libsoc_gpio.h" 16 | 17 | #define STR_BUF 256 18 | 19 | const char gpio_level_strings[2][STR_BUF] = { "0", "1" }; 20 | const char gpio_direction_strings[2][STR_BUF] = { "in", "out" }; 21 | const char gpio_edge_strings[4][STR_BUF] = { "rising", "falling", "none", "both" }; 22 | 23 | void 24 | libsoc_gpio_debug (const char *func, int gpio, char *format, ...) 25 | { 26 | #ifdef DEBUG 27 | 28 | if (libsoc_get_debug ()) 29 | { 30 | va_list args; 31 | 32 | fprintf (stderr, "libsoc-gpio-debug: "); 33 | 34 | va_start (args, format); 35 | vfprintf (stderr, format, args); 36 | va_end (args); 37 | 38 | if (gpio >= 0) 39 | { 40 | fprintf (stderr, " (%d, %s)", gpio, func); 41 | } 42 | else 43 | { 44 | fprintf (stderr, " (NULL, %s)", func); 45 | } 46 | 47 | fprintf (stderr, "\n"); 48 | } 49 | #endif 50 | } 51 | 52 | gpio * 53 | libsoc_gpio_request (unsigned int gpio_id, gpio_mode mode) 54 | { 55 | gpio *new_gpio; 56 | char tmp_str[STR_BUF]; 57 | int shared = 0; 58 | 59 | if (mode != LS_GPIO_SHARED && mode != LS_GPIO_GREEDY && mode != LS_GPIO_WEAK) 60 | { 61 | libsoc_gpio_debug (__func__, gpio_id, 62 | "mode was not set, or invalid," 63 | " setting mode to LS_GPIO_SHARED"); 64 | mode = LS_GPIO_SHARED; 65 | } 66 | 67 | libsoc_gpio_debug (__func__, gpio_id, "requested gpio"); 68 | 69 | sprintf (tmp_str, "/sys/class/gpio/gpio%d/value", gpio_id); 70 | 71 | if (file_valid (tmp_str)) 72 | { 73 | libsoc_gpio_debug (__func__, gpio_id, "GPIO already exported"); 74 | 75 | switch (mode) 76 | { 77 | case LS_GPIO_WEAK: 78 | { 79 | return NULL; 80 | } 81 | 82 | case LS_GPIO_SHARED: 83 | { 84 | shared = 1; 85 | break; 86 | } 87 | 88 | default: 89 | { 90 | break; 91 | } 92 | } 93 | } 94 | else 95 | { 96 | int fd = file_open ("/sys/class/gpio/export", O_SYNC | O_WRONLY); 97 | 98 | if (fd < 0) 99 | return NULL; 100 | 101 | sprintf (tmp_str, "%d", gpio_id); 102 | 103 | if (file_write (fd, tmp_str, STR_BUF) < 0) 104 | return NULL; 105 | 106 | if (file_close (fd)) 107 | return NULL; 108 | 109 | sprintf (tmp_str, "/sys/class/gpio/gpio%d", gpio_id); 110 | 111 | if (!file_valid (tmp_str)) 112 | { 113 | libsoc_gpio_debug (__func__, gpio_id, 114 | "gpio did not export correctly"); 115 | perror ("libsoc-gpio-debug"); 116 | return NULL; 117 | } 118 | } 119 | 120 | new_gpio = malloc (sizeof (gpio)); 121 | if (new_gpio == NULL) 122 | return NULL; 123 | 124 | sprintf (tmp_str, "/sys/class/gpio/gpio%d/value", gpio_id); 125 | 126 | new_gpio->value_fd = file_open (tmp_str, O_SYNC | O_RDWR); 127 | 128 | if (new_gpio->value_fd < 0) 129 | { 130 | free(new_gpio); 131 | return NULL; 132 | } 133 | 134 | new_gpio->gpio = gpio_id; 135 | new_gpio->shared = shared; 136 | new_gpio->callback = NULL; 137 | 138 | // Set up a pollfd in case we are used for polling later 139 | new_gpio->pfd.fd = new_gpio->value_fd; 140 | new_gpio->pfd.events = POLLPRI; 141 | new_gpio->pfd.revents = 0; 142 | 143 | return new_gpio; 144 | } 145 | 146 | int 147 | libsoc_gpio_free (gpio * gpio) 148 | { 149 | char tmp_str[STR_BUF]; 150 | int fd; 151 | 152 | if (gpio == NULL) 153 | { 154 | libsoc_gpio_debug (__func__, -1, "invalid gpio pointer"); 155 | return EXIT_FAILURE; 156 | } 157 | 158 | libsoc_gpio_debug (__func__, gpio->gpio, "freeing gpio"); 159 | 160 | if (gpio->callback != NULL) 161 | { 162 | printf ("Freeing callback!\n"); 163 | // Turn off the callback if there is one enabled 164 | libsoc_gpio_callback_interrupt_cancel (gpio); 165 | } 166 | 167 | if (file_close (gpio->value_fd) < 0) 168 | return EXIT_FAILURE; 169 | 170 | if (gpio->shared == 1) 171 | { 172 | free (gpio); 173 | return EXIT_SUCCESS; 174 | } 175 | 176 | fd = file_open ("/sys/class/gpio/unexport", O_SYNC | O_WRONLY); 177 | 178 | if (fd < 0) 179 | return EXIT_FAILURE; 180 | 181 | sprintf (tmp_str, "%d", gpio->gpio); 182 | 183 | if (file_write (fd, tmp_str, STR_BUF) < 0) 184 | return EXIT_FAILURE; 185 | 186 | if (file_close (fd) < 0) 187 | return EXIT_FAILURE; 188 | 189 | sprintf (tmp_str, "/sys/class/gpio/gpio%d", gpio->gpio); 190 | 191 | if (file_valid (tmp_str)) 192 | { 193 | libsoc_gpio_debug (__func__, gpio->gpio, "freeing failed"); 194 | return EXIT_FAILURE; 195 | } 196 | 197 | free (gpio); 198 | 199 | return EXIT_SUCCESS; 200 | } 201 | 202 | int 203 | libsoc_gpio_set_direction (gpio * current_gpio, gpio_direction direction) 204 | { 205 | int fd; 206 | char path[STR_BUF]; 207 | 208 | if (current_gpio == NULL) 209 | { 210 | libsoc_gpio_debug (__func__, -1, "invalid gpio pointer"); 211 | return EXIT_FAILURE; 212 | } 213 | 214 | libsoc_gpio_debug (__func__, current_gpio->gpio, 215 | "setting direction to %s", 216 | gpio_direction_strings[direction]); 217 | 218 | sprintf (path, "/sys/class/gpio/gpio%d/direction", current_gpio->gpio); 219 | 220 | fd = file_open (path, O_SYNC | O_WRONLY); 221 | 222 | if (fd < 0) 223 | return EXIT_FAILURE; 224 | 225 | if (file_write (fd, gpio_direction_strings[direction], STR_BUF) < 0) 226 | return EXIT_FAILURE; 227 | 228 | if (file_close (fd) < 0) 229 | return EXIT_FAILURE; 230 | 231 | return EXIT_SUCCESS; 232 | } 233 | 234 | gpio_direction 235 | libsoc_gpio_get_direction (gpio * current_gpio) 236 | { 237 | int fd; 238 | char tmp_str[STR_BUF]; 239 | 240 | if (current_gpio == NULL) 241 | { 242 | libsoc_gpio_debug (__func__, -1, "invalid gpio pointer"); 243 | return DIRECTION_ERROR; 244 | } 245 | 246 | sprintf (tmp_str, "/sys/class/gpio/gpio%d/direction", current_gpio->gpio); 247 | 248 | fd = file_open (tmp_str, O_RDONLY); 249 | 250 | if (fd < 0) 251 | return DIRECTION_ERROR; 252 | 253 | lseek (fd, 0, SEEK_SET); 254 | 255 | if (file_read (fd, tmp_str, STR_BUF) < 0) 256 | return DIRECTION_ERROR; 257 | 258 | if (file_close (fd) < 0) 259 | return DIRECTION_ERROR; 260 | 261 | if (strncmp (tmp_str, "in", 2) <= 0) 262 | { 263 | libsoc_gpio_debug (__func__, current_gpio->gpio, 264 | "read direction as input"); 265 | return INPUT; 266 | } 267 | else 268 | { 269 | libsoc_gpio_debug (__func__, current_gpio->gpio, 270 | "read direction as output"); 271 | return OUTPUT; 272 | } 273 | } 274 | 275 | int 276 | libsoc_gpio_set_level (gpio * current_gpio, gpio_level level) 277 | { 278 | if (current_gpio == NULL) 279 | { 280 | libsoc_gpio_debug (__func__, -1, "invalid gpio pointer"); 281 | return EXIT_FAILURE; 282 | } 283 | 284 | libsoc_gpio_debug (__func__, current_gpio->gpio, "setting level to %d", 285 | level); 286 | 287 | if (file_write (current_gpio->value_fd, gpio_level_strings[level], 1) < 0) 288 | return EXIT_FAILURE; 289 | 290 | return EXIT_SUCCESS; 291 | } 292 | 293 | gpio_level 294 | libsoc_gpio_get_level (gpio * current_gpio) 295 | { 296 | char level[2]; 297 | 298 | if (current_gpio == NULL) 299 | { 300 | libsoc_gpio_debug (__func__, -1, "invalid gpio pointer"); 301 | return LEVEL_ERROR; 302 | } 303 | 304 | lseek (current_gpio->value_fd, 0, SEEK_SET); 305 | 306 | if (read (current_gpio->value_fd, level, 2) != 2) 307 | { 308 | libsoc_gpio_debug (__func__, current_gpio->gpio, "level read failed"); 309 | perror ("libgpio"); 310 | return LEVEL_ERROR; 311 | } 312 | 313 | if (level[0] == '0') 314 | { 315 | libsoc_gpio_debug (__func__, current_gpio->gpio, "read level as low"); 316 | return LOW; 317 | } 318 | else 319 | { 320 | libsoc_gpio_debug (__func__, current_gpio->gpio, "read level as high"); 321 | return HIGH; 322 | } 323 | } 324 | 325 | int 326 | libsoc_gpio_set_edge (gpio * current_gpio, gpio_edge edge) 327 | { 328 | int fd; 329 | char path[STR_BUF]; 330 | 331 | if (current_gpio == NULL) 332 | { 333 | libsoc_gpio_debug (__func__, -1, "invalid gpio pointer"); 334 | return EXIT_FAILURE; 335 | } 336 | 337 | libsoc_gpio_debug (__func__, current_gpio->gpio, "setting edge to %s", 338 | gpio_edge_strings[edge]); 339 | 340 | sprintf (path, "/sys/class/gpio/gpio%d/edge", current_gpio->gpio); 341 | 342 | fd = file_open (path, O_SYNC | O_WRONLY); 343 | 344 | if (fd < 0) 345 | return EXIT_FAILURE; 346 | 347 | if (file_write (fd, gpio_edge_strings[edge], STR_BUF) < 0) 348 | return EXIT_FAILURE; 349 | 350 | if (file_close (fd) < 0) 351 | return EXIT_FAILURE; 352 | 353 | return EXIT_SUCCESS; 354 | } 355 | 356 | gpio_edge 357 | libsoc_gpio_get_edge (gpio * current_gpio) 358 | { 359 | int fd; 360 | char tmp_str[STR_BUF]; 361 | 362 | if (current_gpio == NULL) 363 | { 364 | libsoc_gpio_debug (__func__, -1, "invalid gpio pointer"); 365 | return EDGE_ERROR; 366 | } 367 | 368 | sprintf (tmp_str, "/sys/class/gpio/gpio%d/edge", current_gpio->gpio); 369 | 370 | fd = file_open (tmp_str, O_RDONLY); 371 | 372 | if (fd < 0) 373 | return EDGE_ERROR; 374 | 375 | lseek (fd, 0, SEEK_SET); 376 | 377 | if (file_read (fd, tmp_str, STR_BUF) < 0) 378 | return EDGE_ERROR; 379 | 380 | if (file_close (fd) < 0) 381 | return EDGE_ERROR; 382 | 383 | if (strncmp (tmp_str, "r", 1) == 0) 384 | { 385 | libsoc_gpio_debug (__func__, current_gpio->gpio, "read edge as rising"); 386 | return RISING; 387 | } 388 | else if (strncmp (tmp_str, "f", 1) == 0) 389 | { 390 | libsoc_gpio_debug (__func__, current_gpio->gpio, 391 | "read edge as falling"); 392 | return FALLING; 393 | } 394 | else if (strncmp (tmp_str, "b", 1) == 0) 395 | { 396 | libsoc_gpio_debug (__func__, current_gpio->gpio, 397 | "read edge as both"); 398 | return BOTH; 399 | } 400 | else 401 | { 402 | libsoc_gpio_debug (__func__, current_gpio->gpio, "read edge as none"); 403 | return NONE; 404 | } 405 | } 406 | 407 | int 408 | libsoc_gpio_poll (gpio * gpio, int timeout) 409 | { 410 | int rc; 411 | char c; 412 | 413 | // do an initial read to clear interrupt, 414 | rc = lseek(gpio->value_fd, 0, SEEK_SET); 415 | rc = read(gpio->value_fd, &c, 1); 416 | 417 | rc = poll(&gpio->pfd, 1, timeout); 418 | if (rc == -1) 419 | { 420 | libsoc_gpio_debug (__func__, gpio->gpio, "poll failed"); 421 | perror ("libsoc-gpio-debug"); 422 | return LS_INT_ERROR; 423 | } 424 | else if (rc == 1 && gpio->pfd.revents & POLLPRI) 425 | { 426 | // do a final read to clear interrupt 427 | rc = read(gpio->value_fd, &c, 1); 428 | return LS_INT_TRIGGERED; 429 | } 430 | return LS_INT_TIMEOUT; 431 | } 432 | 433 | int 434 | libsoc_gpio_wait_interrupt (gpio * gpio, int timeout) 435 | { 436 | if (gpio == NULL) 437 | { 438 | libsoc_gpio_debug (__func__, -1, "invalid gpio pointer"); 439 | return LS_INT_ERROR; 440 | } 441 | 442 | if (libsoc_gpio_get_direction (gpio) != INPUT) 443 | { 444 | libsoc_gpio_debug (__func__, gpio->gpio, "gpio is not set as input"); 445 | return LS_INT_ERROR; 446 | } 447 | 448 | gpio_edge test_edge = libsoc_gpio_get_edge (gpio); 449 | 450 | if (test_edge == EDGE_ERROR || test_edge == NONE) 451 | { 452 | libsoc_gpio_debug (__func__, gpio->gpio, 453 | "edge must be FALLING, RISING or BOTH"); 454 | return LS_INT_ERROR; 455 | } 456 | 457 | return libsoc_gpio_poll(gpio, timeout); 458 | } 459 | 460 | void * 461 | __libsoc_new_interrupt_callback_thread (void *void_gpio) 462 | { 463 | gpio *gpio = void_gpio; 464 | 465 | pthread_mutex_unlock(&gpio->callback->ready); 466 | 467 | while (1) 468 | { 469 | if (libsoc_gpio_poll(gpio, -1) == LS_INT_TRIGGERED) 470 | { 471 | libsoc_gpio_debug (__func__, gpio->gpio, "caught interrupt"); 472 | gpio->callback->callback_fn (gpio->callback->callback_arg); 473 | } 474 | } 475 | } 476 | 477 | int 478 | libsoc_gpio_callback_interrupt (gpio * gpio, int (*callback_fn) (void *), 479 | void *arg) 480 | { 481 | pthread_t *poll_thread = malloc (sizeof (pthread_t)); 482 | pthread_attr_t pthread_attr; 483 | 484 | pthread_attr_init (&pthread_attr); 485 | pthread_attr_setschedpolicy (&pthread_attr, SCHED_FIFO); 486 | 487 | struct gpio_callback *new_gpio_callback; 488 | 489 | libsoc_gpio_debug (__func__, gpio->gpio, "creating new callback"); 490 | 491 | new_gpio_callback = malloc (sizeof (struct gpio_callback)); 492 | 493 | new_gpio_callback->callback_fn = callback_fn; 494 | new_gpio_callback->callback_arg = arg; 495 | new_gpio_callback->thread = poll_thread; 496 | 497 | gpio->callback = new_gpio_callback; 498 | 499 | pthread_mutex_init(&new_gpio_callback->ready, NULL); 500 | pthread_mutex_lock(&new_gpio_callback->ready); 501 | 502 | int ret = pthread_create (poll_thread, NULL, 503 | __libsoc_new_interrupt_callback_thread, gpio); 504 | 505 | if (ret == 0) 506 | { 507 | // Wait for thread to be initialised and ready 508 | pthread_mutex_lock(&new_gpio_callback->ready); 509 | } 510 | else 511 | { 512 | pthread_mutex_unlock(&gpio->callback->ready); 513 | pthread_mutex_destroy(&gpio->callback->ready); 514 | free (gpio->callback->thread); 515 | free (gpio->callback); 516 | 517 | return EXIT_FAILURE; 518 | } 519 | 520 | return EXIT_SUCCESS; 521 | } 522 | 523 | int 524 | libsoc_gpio_callback_interrupt_cancel (gpio * gpio) 525 | { 526 | if (gpio->callback == NULL) 527 | return EXIT_SUCCESS; 528 | 529 | if (gpio->callback->thread == NULL) 530 | { 531 | libsoc_gpio_debug (__func__, gpio->gpio, "callback thread was NULL"); 532 | return EXIT_FAILURE; 533 | } 534 | 535 | pthread_cancel (*gpio->callback->thread); 536 | 537 | pthread_join (*gpio->callback->thread, NULL); 538 | 539 | pthread_mutex_unlock(&gpio->callback->ready); 540 | pthread_mutex_destroy(&gpio->callback->ready); 541 | 542 | free (gpio->callback->thread); 543 | free (gpio->callback); 544 | 545 | gpio->callback = NULL; 546 | 547 | libsoc_gpio_debug (__func__, gpio->gpio, "callback thread was stopped"); 548 | 549 | return EXIT_SUCCESS; 550 | } 551 | -------------------------------------------------------------------------------- /lib/i2c.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: LGPL-2.1-only */ 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include "libsoc_i2c.h" 13 | #include "libsoc_debug.h" 14 | #include "libsoc_file.h" 15 | 16 | void 17 | libsoc_i2c_debug (const char *func, i2c * i2c, char *format, ...) 18 | { 19 | #ifdef DEBUG 20 | 21 | if (libsoc_get_debug ()) 22 | { 23 | va_list args; 24 | 25 | fprintf (stderr, "libsoc-i2c-debug: "); 26 | 27 | va_start (args, format); 28 | vfprintf (stderr, format, args); 29 | va_end (args); 30 | 31 | if (i2c == NULL) 32 | { 33 | fprintf (stderr, " (NULL, %s)", func); 34 | } 35 | else 36 | { 37 | fprintf (stderr, " (i2c-%d, %d, %s)", i2c->bus, 38 | i2c->address, func); 39 | } 40 | 41 | fprintf (stderr, "\n"); 42 | } 43 | #endif 44 | } 45 | 46 | i2c * 47 | libsoc_i2c_init (uint8_t i2c_bus, uint8_t i2c_address) 48 | { 49 | i2c *i2c_dev; 50 | 51 | libsoc_i2c_debug (__func__, NULL, "initialising i2c bus %d at " 52 | "address %d", i2c_bus, i2c_address); 53 | 54 | i2c_dev = malloc (sizeof (i2c)); 55 | 56 | if (i2c_dev == NULL) 57 | { 58 | libsoc_i2c_debug (__func__, NULL, "failed to allocate memory"); 59 | return NULL; 60 | } 61 | 62 | char path[40]; 63 | 64 | i2c_dev->bus = i2c_bus; 65 | i2c_dev->address = i2c_address; 66 | 67 | sprintf (path, "/dev/i2c-%d", i2c_dev->bus); 68 | 69 | if (!file_valid (path)) 70 | { 71 | libsoc_i2c_debug (__func__, i2c_dev, "%s not a vaild device", path); 72 | goto error; 73 | } 74 | 75 | i2c_dev->fd = file_open (path, O_SYNC | O_RDWR); 76 | 77 | if (i2c_dev->fd < 0) 78 | { 79 | libsoc_i2c_debug (__func__, i2c_dev, "%s could not be opened", path); 80 | goto error; 81 | } 82 | 83 | return i2c_dev; 84 | 85 | error: 86 | 87 | free (i2c_dev); 88 | 89 | return NULL; 90 | } 91 | 92 | int 93 | libsoc_i2c_free (i2c * i2c) 94 | { 95 | if (i2c == NULL) 96 | { 97 | libsoc_i2c_debug (__func__, NULL, "i2c was not valid"); 98 | return EXIT_FAILURE; 99 | } 100 | 101 | libsoc_i2c_debug (__func__, i2c, "freeing i2c device"); 102 | 103 | if (file_close (i2c->fd) < 0) 104 | return EXIT_FAILURE; 105 | 106 | free (i2c); 107 | 108 | return EXIT_SUCCESS; 109 | } 110 | 111 | int 112 | libsoc_i2c_ioctl(i2c * i2c, int num_messages) 113 | { 114 | i2c->packets.msgs = i2c->messages; 115 | i2c->packets.nmsgs = num_messages; 116 | 117 | if (ioctl(i2c->fd, I2C_RDWR, &i2c->packets) < 0) 118 | { 119 | libsoc_i2c_debug(__func__, i2c, "message failed"); 120 | perror ("libsoc-i2c-debug"); 121 | return EXIT_FAILURE; 122 | } 123 | 124 | return EXIT_SUCCESS; 125 | } 126 | 127 | int 128 | libsoc_i2c_set_timeout(i2c * i2c, int timeout) 129 | { 130 | if (ioctl(i2c->fd, I2C_TIMEOUT, timeout) < 0) 131 | { 132 | libsoc_i2c_debug(__func__, i2c, "setting timeout failed"); 133 | perror ("libsoc-i2c-debug"); 134 | return EXIT_FAILURE; 135 | } 136 | 137 | libsoc_i2c_debug(__func__, i2c, "timeout set to %dms", (timeout*10)); 138 | 139 | return EXIT_SUCCESS; 140 | } 141 | 142 | int 143 | libsoc_i2c_write (i2c * i2c, uint8_t * buffer, uint16_t len) 144 | { 145 | if (i2c == NULL || buffer == NULL) 146 | { 147 | libsoc_i2c_debug (__func__, i2c, "i2c | buffer was NULL"); 148 | return EXIT_FAILURE; 149 | } 150 | 151 | libsoc_i2c_debug(__func__, i2c, "Writing buffer of length %d", len); 152 | 153 | i2c->messages[0].addr = i2c->address; 154 | i2c->messages[0].flags = 0; 155 | i2c->messages[0].len = len; 156 | i2c->messages[0].buf = buffer; 157 | 158 | return libsoc_i2c_ioctl(i2c, 1); 159 | } 160 | 161 | int 162 | libsoc_i2c_read (i2c * i2c, uint8_t * buffer, uint16_t len) 163 | { 164 | if (i2c == NULL || buffer == NULL) 165 | { 166 | libsoc_i2c_debug (__func__, i2c, "i2c | buffer was NULL"); 167 | return EXIT_FAILURE; 168 | } 169 | 170 | libsoc_i2c_debug(__func__, i2c, "Reading buffer of length %d", len); 171 | 172 | i2c->messages[0].addr = i2c->address; 173 | i2c->messages[0].flags = I2C_M_RD; 174 | i2c->messages[0].len = len; 175 | i2c->messages[0].buf = buffer; 176 | 177 | return libsoc_i2c_ioctl(i2c, 1); 178 | } 179 | 180 | -------------------------------------------------------------------------------- /lib/include/libsoc_board.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: LGPL-2.1-only */ 2 | 3 | #ifndef _LIBSOC_GPIO_ID_H_ 4 | #define _LIBSOC_GPIO_ID_H_ 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | #include "libsoc_conffile.h" 11 | 12 | /** 13 | * \struct board_config 14 | * \brief a struct to hold board specific information 15 | * \param conf* - the board config file 16 | */ 17 | 18 | typedef struct { 19 | conffile *conf; 20 | } board_config; 21 | 22 | /** 23 | * \fn board_config* libsoc_board_init() 24 | * \brief initialize board specific values like gpio mappings 25 | * \return board_config* or NULL 26 | */ 27 | 28 | board_config *libsoc_board_init(); 29 | 30 | /** 31 | * \fn int libsoc_board_free(board_config *config) 32 | * \brief free up memory created from call to libsoc_board_init 33 | * \param board_config* config - valid pointer to board_config 34 | * \return void 35 | */ 36 | 37 | void libsoc_board_free(board_config *config); 38 | 39 | /** 40 | * \fn int libsoc_gpio_id(board_config* config, const char* pin) 41 | * \brief find the gpio id of a given pin name 42 | * \param board_config* config - valid pointer to board_config 43 | * \param char* pin - a pin name for the board like "P49" 44 | * \return >=0 for gpio id or -1 on failure 45 | */ 46 | 47 | int libsoc_board_gpio_id(board_config *config, const char* pin); 48 | 49 | #ifdef __cplusplus 50 | } 51 | #endif 52 | #endif 53 | -------------------------------------------------------------------------------- /lib/include/libsoc_conffile.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: LGPL-2.1-only */ 2 | 3 | #ifndef _LIBSOC_CONFFILE_H_ 4 | #define _LIBSOC_CONFFILE_H_ 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | /** 11 | * \struct keyval 12 | * \brief a linked list of key-value pairs 13 | * \param char *key - the name of the key 14 | * \param char *val - the value of the key 15 | * \param keyval* - the next key-value pair 16 | */ 17 | 18 | typedef struct keyval { 19 | char *key; 20 | char *val; 21 | struct keyval *next; 22 | } keyval; 23 | 24 | /** 25 | * \struct section 26 | * \brief Contains the key-value pairs in a given section 27 | * \param char *name - the section name 28 | * \param keyval *settings - the key-value pairs for the section 29 | * \param section* - the next section in the list 30 | */ 31 | 32 | typedef struct section { 33 | char name[16]; 34 | keyval *settings; 35 | struct section *next; 36 | } section; 37 | 38 | /** 39 | * \struct confile 40 | * \brief Contains a list of sections 41 | * \param section* section - the HEAD pointer of the section list 42 | */ 43 | typedef struct conffile { 44 | section *sections; 45 | } conffile; 46 | 47 | /** 48 | * \fn conffile *conffile_load(const char *path) 49 | * \brief Loads a given configuration file 50 | * \param char* path - The path to the file 51 | * \return NULL on error 52 | */ 53 | conffile* conffile_load(const char *path); 54 | 55 | /** 56 | * \fn conffile *conffile_free(conffile*) 57 | * \brief Frees memory allocated in conffile struct 58 | */ 59 | void conffile_free(conffile *conf); 60 | 61 | /** 62 | * \fn const char *conffile_get(conffile *conf, const char *sectname, const char *key, const char *defval) 63 | * \brief Find the key in the given section of conffile and return its value. 64 | * \return The value found in the conffile or defval if one is not found. 65 | */ 66 | const char* conffile_get(conffile *conf, const char *sectname, const char *key, const char *defval); 67 | 68 | /** 69 | * \fn int *conffile_get_int(conffile *conf, const char *sectname, const char *key, int defval) 70 | * \brief Find the key in the given section of conffile and return its integer 71 | * value. 72 | * \brief Returns the value for the given section and key or defval if the key 73 | * isn't found or is not numeric. 74 | */ 75 | int conffile_get_int(conffile *conf, const char *sectname, const char *key, int defval); 76 | 77 | #ifdef __cplusplus 78 | } 79 | #endif 80 | #endif 81 | -------------------------------------------------------------------------------- /lib/include/libsoc_debug.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: LGPL-2.1-only */ 2 | 3 | #ifndef _LIBSOC_DEBUG_H_ 4 | #define _LIBSOC_DEBUG_H_ 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | void libsoc_debug(const char *func, char *format, ...) __attribute__((format(printf, 2, 3))); 11 | void libsoc_warn(const char *format, ...) __attribute__((format(printf, 1, 2))); 12 | int libsoc_get_debug(); 13 | void libsoc_set_debug(int level); 14 | 15 | #ifdef __cplusplus 16 | } 17 | #endif 18 | #endif 19 | -------------------------------------------------------------------------------- /lib/include/libsoc_file.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: LGPL-2.1-only */ 2 | 3 | #ifndef _LIBSOC_FILE_H_ 4 | #define _LIBSOC_FILE_H_ 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | int file_open(const char* path, int flags); 11 | int file_write(int fd, const char* str, int len); 12 | int file_read(int fd, void *buf, int count); 13 | int file_valid(char* path); 14 | int file_close(int fd); 15 | int file_write_int(char *path, int val); 16 | int file_read_str(char *path, char *tmp, int buf_len); 17 | int file_write_str(char *path, char* buf, int len); 18 | int file_read_int(char *path, int *tmp); 19 | int file_read_int_fd(int fd, int *tmp); 20 | int file_write_int_fd(int fd, int val); 21 | int file_write_int_path(char *path, int val); 22 | char* file_read_contents(const char *path); 23 | 24 | #ifdef __cplusplus 25 | } 26 | #endif 27 | #endif 28 | -------------------------------------------------------------------------------- /lib/include/libsoc_gpio.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: LGPL-2.1-only */ 2 | 3 | #ifndef _LIBSOC_GPIO_H_ 4 | #define _LIBSOC_GPIO_H_ 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | #ifdef __cplusplus 11 | extern "C" { 12 | #endif 13 | 14 | /** 15 | * \struct gpio_callback 16 | * \brief representation of an interrupt callback 17 | * \param int (*callback_fn)(void*) - the function to callback on interrupt 18 | * \param void *callback_arg - the argument to pass to the callback function 19 | * \param pthread_t *thread - the pthread struct on which the poll and 20 | * callback function runs 21 | * \param int ready - signal when the pthread is ready to accept interrupts 22 | */ 23 | 24 | struct gpio_callback { 25 | int (*callback_fn) (void *); 26 | void *callback_arg; 27 | pthread_t *thread; 28 | pthread_mutex_t ready; 29 | }; 30 | 31 | /** 32 | * \struct gpio 33 | * \brief representation of a single requested gpio 34 | * \param unsigned int gpio gpio id 35 | * \param int value_fd file descriptor to gpio value file 36 | * \param struct gpio_callback *callback - struct used to store interrupt 37 | * callback data 38 | * \param int shared - set if the request flag was shared and the GPIO was 39 | * exported on request 40 | */ 41 | 42 | typedef struct { 43 | unsigned int gpio; 44 | int value_fd; 45 | struct gpio_callback *callback; 46 | struct pollfd pfd; 47 | int shared; 48 | } gpio; 49 | 50 | /** 51 | * \enum gpio_int_ret 52 | * \brief defined values for return type of blocked gpio interrupts 53 | */ 54 | 55 | typedef enum { 56 | LS_INT_TRIGGERED = EXIT_SUCCESS, 57 | LS_INT_ERROR = EXIT_FAILURE, 58 | LS_INT_TIMEOUT, 59 | } gpio_int_ret; 60 | 61 | /** 62 | * \enum gpio_direction 63 | * \brief defined values for input/output direction 64 | */ 65 | 66 | typedef enum { 67 | DIRECTION_ERROR = -1, 68 | INPUT = 0, 69 | OUTPUT = 1, 70 | } gpio_direction; 71 | 72 | /** 73 | * \enum gpio_level 74 | * \brief defined values for high/low gpio level 75 | */ 76 | 77 | typedef enum { 78 | LEVEL_ERROR = -1, 79 | LOW = 0, 80 | HIGH = 1, 81 | } gpio_level; 82 | 83 | /** 84 | * \enum gpio_edge 85 | * \brief defined values for rising/falling/none/both gpio edge 86 | */ 87 | 88 | typedef enum { 89 | EDGE_ERROR = -1, 90 | RISING = 0, 91 | FALLING = 1, 92 | NONE = 2, 93 | BOTH = 3, 94 | } gpio_edge; 95 | 96 | /** 97 | * \enum gpio_mode 98 | * 99 | * LS_GPIO_SHARED - if the gpio is already exported then it will not unexport 100 | * the GPIO on free. If it is not exported, then it will 101 | * unexport on free. 102 | * 103 | * LS_GPIO_GREEDY - will succeed if the GPIO is already exported, but will 104 | * always unexport the GPIO on free. 105 | * 106 | * LS_GPIO_WEAK - will fail if GPIO is already exported, will always unexport 107 | * on free. 108 | */ 109 | 110 | typedef enum gpio_mode { 111 | LS_GPIO_SHARED, 112 | LS_GPIO_GREEDY, 113 | LS_GPIO_WEAK, 114 | } gpio_mode; 115 | 116 | /** 117 | * \fn gpio* libsoc_gpio_request(unsigned int gpio_id) 118 | * \brief request a gpio to use 119 | * \param unsigned int gpio_id - the id of the gpio you wish to request 120 | * \param unsigned int mode - mode for opening GPIO 121 | * \return pointer to gpio* on success NULL on fail 122 | * 123 | */ 124 | 125 | gpio *libsoc_gpio_request(unsigned int gpio_id, enum gpio_mode mode); 126 | 127 | /** 128 | * \fn int libsoc_gpio_free(gpio* gpio) 129 | * \brief free a previously requested gpio 130 | * \param gpio* gpio - valid pointer to a requested gpio 131 | * \return EXIT_SUCCESS or EXIT_FAILURE 132 | */ 133 | 134 | int libsoc_gpio_free(gpio * gpio); 135 | 136 | /** 137 | * \fn int libsoc_gpio_set_direction(gpio* current_gpio, gpio_direction direction) 138 | * \brief set GPIO to input or output 139 | * \param gpio* current_gpio - pointer to gpio struct on which to set the direction 140 | * \param gpio_direction direction - enumerated direction, INPUT or OUTPUT 141 | * \return EXIT_SUCCESS or EXIT_FAILURE 142 | */ 143 | 144 | int libsoc_gpio_set_direction(gpio * current_gpio, gpio_direction direction); 145 | 146 | /** 147 | * \fn gpio_direction libsoc_gpio_get_direction(gpio* current_gpio) 148 | * \brief get the current direction of the gpio 149 | * \param gpio* current_gpio - pointer to gpio struct on which to get the direction 150 | * \return current GPIO direction, INPUT or OUTPUT 151 | */ 152 | 153 | gpio_direction libsoc_gpio_get_direction(gpio * current_gpio); 154 | 155 | /** 156 | * \fn in libsoc_gpio_set_level(gpio* current_gpio, gpio_level level) 157 | * \brief set the GPIO level to high or low 158 | * \param gpio* current_gpio - pointer to gpio struct on which to set the level 159 | * \param gpio_level level = enumerated gpio_level, HIGH or LOW 160 | * \return EXIT_SUCCES or EXIT_FAILURE 161 | */ 162 | 163 | int libsoc_gpio_set_level(gpio * current_gpio, gpio_level level); 164 | 165 | /** 166 | * \fn gpio_level libsoc_gpio_get_level(gpio* current_gpio) 167 | * \brief gets the current gpio level 168 | * \param gpio* current_gpio - pointer to gpio struct on which to get the level 169 | * \return gpio_level, HIGH or LOW 170 | */ 171 | 172 | gpio_level libsoc_gpio_get_level(gpio * current_gpio); 173 | 174 | /** 175 | * \fn gpio_edge libsoc_gpio_get_edge(gpio* current_gpio) 176 | * \brief gets the current gpio edge value 177 | * \param gpio* current_gpio - pointer to gpio struct on which to get the edge 178 | * \return gpio_edge, RISING, FALLING or NONE 179 | */ 180 | 181 | gpio_edge libsoc_gpio_get_edge(gpio * current_gpio); 182 | 183 | /** 184 | * \fn int libsoc_gpio_set_edge(gpio* current_gpio, gpio_edge edge) 185 | * \brief sets the edge value of a gpio for interrupt generation 186 | * \param gpio* current_gpio - the gpio for which you wish to set the edge 187 | * \param gpio_edge edge - enumerated edge value, RISING, FALLING or NONE 188 | * \return EXIT_SUCCESS or EXIT FAILURE 189 | */ 190 | 191 | int libsoc_gpio_set_edge(gpio * current_gpio, gpio_edge edge); 192 | 193 | /** 194 | * \fn int libsoc_gpio_wait_interrupt(gpio* gpio, int timeout) 195 | * \brief takes a gpio and waits for length of timeout or until an 196 | * interrupt occurs. Will return EXIT_SUCCESS on interrupt or 197 | * EXIT_FAILURE on error or timeout. 198 | * \param gpio* gpio - the gpio for which you want to wait on interrupt 199 | * \param int timeout - the max length of time to wait for interrupt in 200 | * milliseconds 201 | * \return EXIT_SUCCESS on interrupt caught, EXIT_FAILURE on error or 202 | * interrupt missed 203 | */ 204 | 205 | int libsoc_gpio_wait_interrupt(gpio * gpio, int timeout); 206 | 207 | /** 208 | * \fn int libsoc_gpio_callback_interrupt(gpio* gpio, int (*callback_fn)(void*), void* arg) 209 | * \brief takes a gpio and a callback function, when an interrupt occurs 210 | * on the edge previously specified, the callback function is called 211 | * \param gpio* gpio - the gpio for which you want the interrupt to 212 | * trigger the callback function 213 | * \param int (*callback_fn)(void*) - the function you wish to call with 214 | * a void* pointer to a possible value you may wish to use in the callback. 215 | * \param void* arg - pointer to data you wish to use in the callback function 216 | * \return EXIT_SUCCESS or EXIT_FAILURE 217 | */ 218 | 219 | int libsoc_gpio_callback_interrupt(gpio * gpio, int (*callback_fn) (void *), 220 | void *arg); 221 | 222 | /** 223 | * \fn int libsoc_gpio_callback_interrupt_cancel(gpio* gpio) 224 | * \brief cancel a callback on a gpio interrupt 225 | * \param gpio* gpio - gpio with a valid callback enabled 226 | * \return EXIT_SUCCESS or EXIT_FAILURE 227 | */ 228 | 229 | int libsoc_gpio_callback_interrupt_cancel(gpio * gpio); 230 | 231 | #ifdef __cplusplus 232 | } 233 | #endif 234 | #endif 235 | -------------------------------------------------------------------------------- /lib/include/libsoc_i2c.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: LGPL-2.1-only */ 2 | 3 | #ifndef _LIBSOC_I2C_H_ 4 | #define _LIBSOC_I2C_H_ 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | #ifdef __cplusplus 11 | extern "C" { 12 | #endif 13 | 14 | /** 15 | * \struct i2c 16 | * \brief representation of spi device and chipselect 17 | * \param int fd - file descriptor to open i2c device 18 | * \param uint8_t bus - i2c bus number 19 | * \param uint8_t address - address of i2c device on the bus 20 | */ 21 | 22 | typedef struct { 23 | int fd; 24 | uint8_t bus; 25 | uint8_t address; 26 | struct i2c_rdwr_ioctl_data packets; 27 | struct i2c_msg messages[2]; 28 | } i2c; 29 | 30 | /** 31 | * \fn i2c * libsoc_i2c_init (uint8_t i2c_bus, uint8_t i2c_address) 32 | * \brief initialises new i2c instance at specified address 33 | * \param uint8_t i2c_bus - the linux enumerated bus number 34 | * \param uint8_t i2c_address - 35 | * \return i2c* struct pointer or NULL on failure 36 | */ 37 | i2c * libsoc_i2c_init (uint8_t i2c_bus, uint8_t i2c_address); 38 | 39 | /** 40 | * \fn libsoc_i2c_free (i2c * i2c) 41 | * \brief frees the malloced i2c struct 42 | * \param i2c* i2c - valid i2c struct pointer 43 | * \return EXIT_SUCCESS or EXIT_FAILURE 44 | */ 45 | int libsoc_i2c_free (i2c * i2c); 46 | 47 | /** 48 | * \fn libsoc_i2c_write(i2c *i2c, uint8_t *buffer, uint16_t len) 49 | * \brief write a specified amount of data to i2c slave 50 | * \param i2c *i2c - valid i2c device struct 51 | * \param uint8_t *buffer - pointer to output data buffer 52 | * \param uint16_t len - length of buffer in bytes 53 | * \return EXIT_SUCCESS or EXIT_FAILURE 54 | */ 55 | int libsoc_i2c_write (i2c * i2c, uint8_t * buffer, uint16_t len); 56 | 57 | /** 58 | * \fn libsoc_i2c_read(i2c *i2c, uint8_t *buffer, uint16_t len) 59 | * \brief read a specified amount of data from an i2c slave 60 | * \param i2c *i2c - valid i2c device struct 61 | * \param uint8_t *buffer - pointer to input data buffer 62 | * \param uint16_t len - length of buffer in bytes 63 | * \return EXIT_SUCCESS or EXIT_FAILURE 64 | */ 65 | int libsoc_i2c_read (i2c * i2c, uint8_t * buffer, uint16_t len); 66 | 67 | /** 68 | * \fn libsoc_i2c_set_timeout(i2c *i2c, int timeout) 69 | * \brief set the timeout in is 10's of milliseconds, i.e. a timeout of 70 | * 2 is 2 x 10ms = 20ms 71 | * \param i2c *i2c - valid i2c device struct 72 | * \return EXIT_SUCCESS or EXIT_FAILURE 73 | */ 74 | int libsoc_i2c_set_timeout(i2c * i2c, int timeout); 75 | 76 | #ifdef __cplusplus 77 | } 78 | #endif 79 | #endif 80 | -------------------------------------------------------------------------------- /lib/include/libsoc_pwm.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: LGPL-2.1-only */ 2 | 3 | #ifndef _LIBSOC_PWM_H_ 4 | #define _LIBSOC_PWM_H_ 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | /** 11 | * \struct pwm 12 | * \brief representation of a single requested pwm 13 | * \param unsigned int pwm - pwm num 14 | * \param unsigned int pwm_chip - pwm chip num 15 | * \param int enabled_fd - file descriptor to pwm enable file 16 | * \param int duty_fd - file descriptor to pwm duty_cycle file 17 | * \param int period_fd - file descriptor to pwm period file 18 | * \param int shared - set if the request flag was shared and the pwm was 19 | * exported on request 20 | */ 21 | 22 | typedef struct { 23 | unsigned int chip; 24 | unsigned int pwm; 25 | int enable_fd; 26 | int duty_fd; 27 | int period_fd; 28 | int shared; 29 | } pwm; 30 | 31 | /** 32 | * \enum pwm_enabled 33 | * \brief defined values for pwm enabled/disabled 34 | */ 35 | 36 | typedef enum { 37 | ENABLED_ERROR = -1, 38 | DISABLED = 0, 39 | ENABLED = 1, 40 | } pwm_enabled; 41 | 42 | /** 43 | * \enum pwm_polarity 44 | * \brief defined values for pwm polarity 45 | */ 46 | 47 | typedef enum { 48 | POLARITY_ERROR = -1, 49 | NORMAL = 0, 50 | INVERSED = 1, 51 | } pwm_polarity; 52 | 53 | /** 54 | * \enum shared_mode 55 | * 56 | * LS_PWM_SHARED - if the pwm is already exported then it will not unexport 57 | * the PWM on free. If it is not exported, then it will 58 | * unexport on free. 59 | * 60 | * LS_PWM_GREEDY - will succeed if the PWM is already exported, but will 61 | * always unexport the PWM on free. 62 | * 63 | * LS_PWM_WEAK - will fail if PWM is already exported, will always unexport 64 | * on free. 65 | */ 66 | 67 | typedef enum { 68 | LS_PWM_SHARED, 69 | LS_PWM_GREEDY, 70 | LS_PWM_WEAK, 71 | } shared_mode; 72 | 73 | /** 74 | * \fn pwm* libsoc_pwm_request(unsigned int pwm_chip, unsigned int pwm_num) 75 | * \brief request a pwm to use 76 | * \param unsigned int pwm_chip - the chip number that controls the pwm you 77 | wish to use 78 | * \param unsigned int pwm_num - the pwm number number within your pwm chip 79 | * \param unsigned int mode - mode for opening PWM 80 | * \return pointer to pwm* on success NULL on fail 81 | * 82 | */ 83 | 84 | pwm* libsoc_pwm_request(unsigned int pwm_chip, unsigned int pwm_num, 85 | shared_mode mode); 86 | 87 | /** 88 | * \fn int libsoc_pwm_free(pwm* pwm) 89 | * \brief free a previously requested pwm 90 | * \param pwm* pwm - valid pointer to a requested pwm 91 | * \return EXIT_SUCCESS or EXIT_FAILURE 92 | */ 93 | 94 | int libsoc_pwm_free(pwm *pwm); 95 | 96 | /** 97 | * \fn int libsoc_pwm_set_enabled(pwm *pwm, pwm_enabled enabled) 98 | * \brief set PWM enabled/disabled 99 | * \param pwm* pwm - pointer to pwm struct on which to set enabled 100 | * \param pwm_enabled enabled - enumerated enabled status, ENABLED or DISABLED 101 | * \return EXIT_SUCCESS or EXIT_FAILURE 102 | */ 103 | 104 | int libsoc_pwm_set_enabled(pwm *pwm, pwm_enabled enabled); 105 | 106 | /** 107 | * \fn libsoc_pwm_get_enabled(pwm *pwm) 108 | * \brief get the current enabled status of the PWM 109 | * \param pwm *pwm - pointer to pwm struct on which to get the enabled status 110 | * \return current PWM enabled status, ENABLED,DISABLED or ERROR_ENABLED 111 | */ 112 | 113 | pwm_enabled libsoc_pwm_get_enabled(pwm *pwm); 114 | 115 | /** 116 | * \fn libsoc_pwm_set_polarity(pwm *pwm, pwm_polarity polarity) 117 | * \brief set the PWM polarity to normal or inverted 118 | * \param pwm *pwm - pointer to pwm struct on which to set the polarity 119 | * \param pwm_polarity = enumerated pwm_polarity NORMAL or INVERTED 120 | * \return EXIT_SUCCESS or EXIT_FAILURE 121 | */ 122 | 123 | int libsoc_pwm_set_polarity(pwm *pwm, pwm_polarity polarity); 124 | 125 | /** 126 | * \fn libsoc_pwm_get_polarity(pwm *pwm) 127 | * \brief gets the current pwm polarity 128 | * \param pwm *pwm - pointer to pwm struct on which to get the polarity 129 | * \return pwm_polarity - NORMAL, INVERTED or ERROR_POLARITY 130 | */ 131 | 132 | pwm_polarity libsoc_pwm_get_polarity(pwm *pwm); 133 | 134 | /** 135 | * \fn libsoc_pwm_set_duty_cycle(pwm *pwm, int duty) 136 | * \brief set the PWM duty cycle (active time of the PWM signal) 137 | * \param pwm *pwm - pointer to valid pwm struct 138 | * \param int duty - duty value in nanoseconds, must be less than period 139 | * \return EXIT_SUCCESS or EXIT_FAILURE 140 | */ 141 | 142 | int libsoc_pwm_set_duty_cycle(pwm *pwm, unsigned int duty); 143 | 144 | /** 145 | * \fn libsoc_pwm_get_duty_cycle(pwm *pwm) 146 | * \brief gets the current pwm duty cycle 147 | * \param pwm *pwm - pointer to valid pwm struct 148 | * \return duty_cycle - integer, -1 on failure 149 | */ 150 | 151 | int libsoc_pwm_get_duty_cycle(pwm *pwm); 152 | 153 | /** 154 | * \fn libsoc_pwm_set_period(pwm *pwm, unsigned int period) 155 | * \brief set the PWM period (sum of the active and inactive 156 | * time of the PWM) 157 | * \param pwm *pwm - pointer to valid pwm struct 158 | * \param int period - period value in nanoseconds 159 | * \return EXIT_SUCCESS or EXIT_FAILURE 160 | */ 161 | 162 | int libsoc_pwm_set_period(pwm *pwm, unsigned int period); 163 | 164 | /** 165 | * \fn libsoc_pwm_get_period(pwm *pwm) 166 | * \brief gets the current pwm period 167 | * \param pwm *pwm - pointer to valid pwm struct 168 | * \return period - integer, -1 on failure 169 | */ 170 | 171 | int libsoc_pwm_get_period(pwm *pwm); 172 | 173 | #ifdef __cplusplus 174 | } 175 | #endif 176 | #endif 177 | -------------------------------------------------------------------------------- /lib/include/libsoc_spi.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: LGPL-2.1-only */ 2 | 3 | #ifndef _LIBSOC_SPI_H_ 4 | #define _LIBSOC_SPI_H_ 5 | 6 | #include 7 | 8 | #ifdef __cplusplus 9 | extern "C" { 10 | #endif 11 | 12 | /** 13 | * \struct spi 14 | * \brief representation of spi device and chipselect 15 | * \param int fd - file descriptor to open spidev character device 16 | * \param struct gpio_callback *callback - struct used to store interrupt 17 | * callback data 18 | * \param uint16_t spi_dev - major number of spi device 19 | * \param uint8_t spi_dev - minor number of spi device 20 | */ 21 | 22 | typedef struct { 23 | int fd; 24 | uint16_t spi_dev; 25 | uint8_t chip_select; 26 | } spi; 27 | 28 | /** 29 | * \enum gpio_direction 30 | * \brief defined values for bits per word 31 | */ 32 | typedef enum { 33 | BITS_8 = 8, 34 | BITS_16 = 16, 35 | BPW_ERROR, 36 | } spi_bpw; 37 | 38 | /** 39 | * \enum gpio_direction 40 | * \brief defined values for spi modes 41 | */ 42 | typedef enum { 43 | MODE_0 = 0, 44 | MODE_1 = 1, 45 | MODE_2 = 2, 46 | MODE_3 = 3, 47 | MODE_ERROR, 48 | } spi_mode; 49 | 50 | /** 51 | * \fn spi* libsoc_spi_init (uint16_t spidev_device, uint8_t chip_select) 52 | * \brief opens the spidev character device and intitialises a new spi 53 | * struct 54 | * \param uint16_t spidev_device - the major spidev number 55 | * \param uint8_t spidev_device - the minor spidev number 56 | * \return spi* struct pointer or NULL on failure 57 | */ 58 | spi* libsoc_spi_init (uint16_t spidev_device, uint8_t chip_select); 59 | 60 | /** 61 | * \fn int libsoc_spi_free(spi* spi) 62 | * \brief frees the malloced spi struct 63 | * \param spi* spi - valid spi struct pointer 64 | * \return EXIT_SUCCESS or EXIT_FAILURE 65 | */ 66 | int libsoc_spi_free(spi* spi); 67 | 68 | /** 69 | * \fn int libsoc_spi_set_mode(spi* spi, spi_mode mode) 70 | * \brief sets the spi mode for the spi device 71 | * \param spi* spi - valid spi struct pointer 72 | * \param enum spi_mode - valid modes are as follows: 73 | * -MODE_0, MODE_1, MODE_2, MODE_3 74 | * Essential Reading: 75 | * - https://www.kernel.org/doc/Documentation/spi/spi-summary 76 | * - http://www.diolan.com/dln_doc/spi-transfer-modes.html 77 | * - http://blackfin.uclinux.org/doku.php?id=spi 78 | * \return EXIT_SUCCESS or EXIT_FAILURE 79 | */ 80 | int libsoc_spi_set_mode(spi* spi, spi_mode mode); 81 | 82 | /** 83 | * \fn int libsoc_spi_set_bits_per_word(spi* spi, spi_bpw bpw) 84 | * \brief sets the bits per word of the spi transfer, either 8 or 16 85 | * \param spi* spi - valid spi struct pointer 86 | * \param enum spi_bpw - bits per word eith BITS_8 or BITS_16 87 | * \return EXIT_SUCCESS or EXIT_FAILURE 88 | */ 89 | int libsoc_spi_set_bits_per_word(spi* spi, spi_bpw bpw); 90 | 91 | /** 92 | * \fn int libsoc_spi_set_speed(spi* spi, uint32_t speed) 93 | * \brief sets the speed of the spi bus, speed can sometimes be changed 94 | * to a sensible value by the kernel, so always do a get and check after 95 | * setting the speed. 96 | * \param spi* spi - valid spi struct pointer 97 | * \param uint32_t speed - set the spi bus speed in Hz 98 | * \return EXIT_SUCCESS or EXIT_FAILURE 99 | */ 100 | int libsoc_spi_set_speed(spi* spi, uint32_t speed); 101 | 102 | /** 103 | * \fn spi_mode libsoc_spi_get_mode(spi* spi) 104 | * \brief gets the current mode of the spi bus 105 | * \param spi* spi - valid spi struct pointer 106 | * \return enum spi_mode - MODE_0/1/2/3 on success, MODE_ERROR on fail 107 | */ 108 | spi_mode libsoc_spi_get_mode(spi* spi); 109 | 110 | /** 111 | * \fn uint32_t libsoc_spi_get_speed(spi* spi) 112 | * \brief gets the current speed of the spi bus 113 | * \param spi* spi - valid spi struct pointer 114 | * \return uint32 - current speed of spi bus in Hz 115 | */ 116 | uint32_t libsoc_spi_get_speed(spi* spi); 117 | 118 | /** 119 | * \fn spi_bpw libsoc_spi_get_bits_per_word(spi* spi) 120 | * \brief gets the current bits per word of the spi bus 121 | * \param spi* spi - valid spi struct pointer 122 | * \return enum spi_bpw - BITS_8/16 on success, BITS_ERROR on fail 123 | */ 124 | spi_bpw libsoc_spi_get_bits_per_word(spi* spi); 125 | 126 | /** 127 | * \fn int libsoc_spi_write(spi* spi, uint8_t* tx, uint32_t len) 128 | * \brief writes data to the spi bus 129 | * \param spi* spi - valid spi struct pointer 130 | * \param uint8_t* tx - array of bytes to send on the bus 131 | * \param uint32_t len - the length of the transfer in bytes 132 | * \return EXIT_SUCCESS or EXIT_FAILURE 133 | */ 134 | int libsoc_spi_write(spi* spi, uint8_t* tx, uint32_t len); 135 | 136 | /** 137 | * \fn int libsoc_spi_read(spi* spi, uint8_t* rx, uint32_t len) 138 | * \brief reads data from the spi bus 139 | * \param spi* spi - valid spi struct pointer 140 | * \param uint8_t* rx - array of bytes to populate with data from the bus 141 | * \param uint32_t len - the length of the transfer in bytes 142 | * \return EXIT_SUCCESS or EXIT_FAILURE 143 | */ 144 | int libsoc_spi_read(spi* spi, uint8_t* rx, uint32_t len); 145 | 146 | /** 147 | * \fn int libsoc_spi_rw(spi* spi, uint8_t* tx, uint8_t* rx, uint32_t len) 148 | * \brief duplex read/write to the spi bus, allows writing data and then 149 | * reading back in one single transaction, or writing and reading at the 150 | * same time. 151 | * \param spi* spi - valid spi struct pointer 152 | * \param uint8_t* tx - array of bytes to send on the bus 153 | * \param uint8_t* rx - array of bytes to populate with data from the bus 154 | * \param uint32_t len - the length of the transfer in bytes 155 | * \return EXIT_SUCCESS or EXIT_FAILURE 156 | */ 157 | int libsoc_spi_rw(spi* spi, uint8_t* tx, uint8_t* rx, uint32_t len); 158 | 159 | #ifdef __cplusplus 160 | } 161 | #endif 162 | #endif 163 | -------------------------------------------------------------------------------- /lib/pwm.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: LGPL-2.1-only */ 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "libsoc_file.h" 12 | #include "libsoc_debug.h" 13 | #include "libsoc_pwm.h" 14 | 15 | #define STR_BUF 256 16 | 17 | static char pwm_polarity_strings[2][STR_BUF] = { "normal", "inversed" }; 18 | static char pwm_enabled_strings[2][STR_BUF] = { "0", "1" }; 19 | 20 | void libsoc_pwm_debug (const char *func, unsigned int chip, 21 | unsigned int pwm, char *format, ...) 22 | { 23 | #ifdef DEBUG 24 | if (libsoc_get_debug ()) 25 | { 26 | va_list args; 27 | 28 | fprintf (stderr, "libsoc-pwm-debug: "); 29 | 30 | va_start (args, format); 31 | vfprintf (stderr, format, args); 32 | va_end (args); 33 | 34 | fprintf (stderr, " ((%d,%d), %s)", chip, pwm, func); 35 | 36 | fprintf (stderr, "\n"); 37 | } 38 | #endif 39 | } 40 | 41 | pwm* libsoc_pwm_request (unsigned int chip, unsigned int pwm_num, 42 | shared_mode mode) 43 | { 44 | pwm *new_pwm; 45 | char tmp_str[STR_BUF]; 46 | int shared = 0; 47 | 48 | if (mode != LS_PWM_SHARED && mode != LS_PWM_GREEDY && mode != LS_PWM_WEAK) 49 | { 50 | libsoc_pwm_debug (__func__, chip, pwm_num, 51 | "mode was not set, or invalid, setting mode to LS_PWM_SHARED"); 52 | 53 | mode = LS_PWM_SHARED; 54 | } 55 | 56 | libsoc_pwm_debug (__func__, chip, pwm_num, "requested PWM"); 57 | 58 | sprintf (tmp_str, "/sys/class/pwm/pwmchip%d/pwm%d/enable", chip, pwm_num); 59 | 60 | if (file_valid (tmp_str)) 61 | { 62 | libsoc_pwm_debug(__func__, chip, pwm_num, "PWM already exported"); 63 | 64 | switch(mode) 65 | { 66 | case LS_PWM_WEAK: 67 | { 68 | return NULL; 69 | } 70 | 71 | case LS_PWM_SHARED: 72 | { 73 | shared = 1; 74 | break; 75 | } 76 | 77 | default: 78 | { 79 | break; 80 | } 81 | } 82 | } 83 | else 84 | { 85 | sprintf(tmp_str, "/sys/class/pwm/pwmchip%d/export", chip); 86 | 87 | if (file_write_int_path(tmp_str, pwm_num) == EXIT_FAILURE) 88 | { 89 | libsoc_pwm_debug(__func__, chip, pwm_num, "write failed"); 90 | return NULL; 91 | } 92 | 93 | sprintf(tmp_str, "/sys/class/pwm/pwmchip%d/pwm%d/enable", chip, pwm_num); 94 | 95 | if (!file_valid(tmp_str)) 96 | { 97 | libsoc_pwm_debug(__func__, chip, pwm_num, 98 | "failed to export PWM"); 99 | 100 | perror("libsoc-pwm-debug"); 101 | return NULL; 102 | } 103 | } 104 | 105 | new_pwm = malloc(sizeof(pwm)); 106 | 107 | sprintf(tmp_str, "/sys/class/pwm/pwmchip%d/pwm%d/enable", chip, pwm_num); 108 | new_pwm->enable_fd = file_open(tmp_str, O_SYNC | O_RDWR); 109 | 110 | sprintf(tmp_str, "/sys/class/pwm/pwmchip%d/pwm%d/period", chip, pwm_num); 111 | new_pwm->period_fd = file_open(tmp_str, O_SYNC | O_RDWR); 112 | 113 | sprintf(tmp_str, "/sys/class/pwm/pwmchip%d/pwm%d/duty_cycle", chip, pwm_num); 114 | new_pwm->duty_fd = file_open(tmp_str, O_SYNC | O_RDWR); 115 | 116 | if (new_pwm->enable_fd < 0 || new_pwm->period_fd < 0 || new_pwm->duty_fd < 0) 117 | { 118 | free(new_pwm); 119 | libsoc_pwm_debug(__func__, chip, pwm_num, "Failed to open pwm sysfs file: %d", new_pwm->enable_fd); 120 | return NULL; 121 | } 122 | 123 | new_pwm->chip = chip; 124 | new_pwm->pwm = pwm_num; 125 | new_pwm->shared = shared; 126 | 127 | return new_pwm; 128 | } 129 | 130 | int libsoc_pwm_free(pwm *pwm) 131 | { 132 | char path[STR_BUF]; 133 | 134 | if (pwm == NULL) 135 | { 136 | libsoc_pwm_debug(__func__, -1, -1, "invalid pwm pointer"); 137 | return EXIT_FAILURE; 138 | } 139 | 140 | libsoc_pwm_debug(__func__, pwm->chip, pwm->pwm, "freeing pwm"); 141 | 142 | if (file_close(pwm->enable_fd) < 0) 143 | { 144 | return EXIT_FAILURE; 145 | } 146 | 147 | if (file_close(pwm->period_fd) < 0) 148 | { 149 | return EXIT_FAILURE; 150 | } 151 | 152 | if (file_close(pwm->duty_fd) < 0) 153 | { 154 | return EXIT_FAILURE; 155 | } 156 | 157 | if (pwm->shared == 1) 158 | { 159 | free(pwm); 160 | return EXIT_SUCCESS; 161 | } 162 | 163 | sprintf(path, "/sys/class/pwm/pwmchip%d/unexport", pwm->chip); 164 | 165 | file_write_int_path(path, pwm->pwm); 166 | 167 | sprintf(path, "/sys/class/pwm/pwmchip%d/pwm%d", pwm->chip, pwm->pwm); 168 | 169 | if (file_valid(path)) 170 | { 171 | libsoc_pwm_debug(__func__, pwm->chip, pwm->pwm, "freeing failed"); 172 | return EXIT_FAILURE; 173 | } 174 | 175 | free(pwm); 176 | 177 | return EXIT_SUCCESS; 178 | } 179 | 180 | int libsoc_pwm_set_enabled(pwm *pwm, pwm_enabled enabled) 181 | { 182 | char path[STR_BUF]; 183 | 184 | if (pwm == NULL) 185 | { 186 | libsoc_pwm_debug(__func__, -1, -1, "invalid pwm pointer"); 187 | return EXIT_FAILURE; 188 | } 189 | 190 | if (enabled != ENABLED && enabled != DISABLED) 191 | { 192 | return EXIT_FAILURE; 193 | } 194 | 195 | libsoc_pwm_debug(__func__, pwm->chip, pwm->pwm, 196 | "setting enabled to %s", pwm_enabled_strings[enabled]); 197 | 198 | sprintf(path, "/sys/class/pwm/pwmchip%d/pwm%d/enable", pwm->chip, pwm->pwm); 199 | 200 | return file_write_str(path, pwm_enabled_strings[enabled], 1); 201 | } 202 | 203 | pwm_enabled libsoc_pwm_get_enabled(pwm *pwm) 204 | { 205 | int val; 206 | 207 | if (pwm == NULL) 208 | { 209 | libsoc_pwm_debug(__func__, -1, -1, "invalid pwm pointer"); 210 | return ENABLED_ERROR; 211 | } 212 | 213 | if (file_read_int_fd(pwm->enable_fd, &val) == EXIT_FAILURE) 214 | { 215 | return ENABLED_ERROR; 216 | } 217 | 218 | if(val == 1) 219 | { 220 | libsoc_pwm_debug(__func__, pwm->chip, pwm->pwm, 221 | "read as enabled"); 222 | return ENABLED; 223 | } 224 | else if (val == 0) 225 | { 226 | libsoc_pwm_debug(__func__, pwm->chip, pwm->pwm, 227 | "read as disabled"); 228 | return DISABLED; 229 | } 230 | else 231 | { 232 | return ENABLED_ERROR; 233 | } 234 | } 235 | 236 | int libsoc_pwm_set_period(pwm *pwm, unsigned int period) 237 | { 238 | if (pwm == NULL) 239 | { 240 | libsoc_pwm_debug(__func__, -1, -1, "invalid pwm pointer"); 241 | return EXIT_FAILURE; 242 | } 243 | 244 | libsoc_pwm_debug(__func__, pwm->chip, pwm->pwm, 245 | "setting period to %d", period); 246 | 247 | return file_write_int_fd(pwm->period_fd, period); 248 | } 249 | 250 | int libsoc_pwm_set_duty_cycle(pwm *pwm, unsigned int duty) 251 | { 252 | if (pwm == NULL) 253 | { 254 | libsoc_pwm_debug(__func__, -1, -1, "invalid pwm pointer"); 255 | return EXIT_FAILURE; 256 | } 257 | 258 | libsoc_pwm_debug(__func__, pwm->chip, pwm->pwm, 259 | "setting duty to %d", duty); 260 | 261 | return file_write_int_fd(pwm->duty_fd, duty); 262 | } 263 | 264 | int libsoc_pwm_get_period(pwm *pwm) 265 | { 266 | int period = -1; 267 | 268 | if (pwm == NULL) 269 | { 270 | libsoc_pwm_debug(__func__, -1, -1, "invalid pwm pointer"); 271 | return -1; 272 | } 273 | 274 | file_read_int_fd(pwm->period_fd, &period); 275 | 276 | libsoc_pwm_debug(__func__, pwm->chip, pwm->pwm, "got period as %d", period); 277 | 278 | return period; 279 | } 280 | 281 | int libsoc_pwm_get_duty_cycle(pwm *pwm) 282 | { 283 | int duty = -1; 284 | 285 | if (pwm == NULL) 286 | { 287 | libsoc_pwm_debug(__func__, -1, -1, "invalid pwm pointer"); 288 | return -1; 289 | } 290 | 291 | file_read_int_fd(pwm->duty_fd, &duty); 292 | 293 | libsoc_pwm_debug(__func__, pwm->chip, pwm->pwm, "got duty as %d", duty); 294 | 295 | return duty; 296 | } 297 | 298 | int libsoc_pwm_set_polarity(pwm *pwm, pwm_polarity polarity) 299 | { 300 | char path[STR_BUF]; 301 | 302 | if (pwm == NULL) 303 | { 304 | libsoc_pwm_debug(__func__, -1, -1, "invalid pwm pointer"); 305 | return EXIT_FAILURE; 306 | } 307 | 308 | if (polarity != NORMAL && polarity != INVERSED) 309 | { 310 | return EXIT_FAILURE; 311 | } 312 | 313 | libsoc_pwm_debug(__func__, pwm->chip, pwm->pwm, 314 | "setting polarity to %s", pwm_polarity_strings[polarity]); 315 | 316 | sprintf(path, "/sys/class/pwm/pwmchip%d/pwm%d/polarity", pwm->chip, pwm->pwm); 317 | 318 | return file_write_str(path, pwm_polarity_strings[polarity], STR_BUF); 319 | } 320 | 321 | int libsoc_pwm_get_polarity(pwm *pwm) 322 | { 323 | int polarity; 324 | char path[STR_BUF]; 325 | char tmp_str[1]; 326 | 327 | if (pwm == NULL) 328 | { 329 | libsoc_pwm_debug(__func__, -1, -1, "invalid pwm pointer"); 330 | return EXIT_FAILURE; 331 | } 332 | 333 | sprintf(path, "/sys/class/pwm/pwmchip%d/pwm%d/polarity", pwm->chip, pwm->pwm); 334 | 335 | if (file_read_str(path, tmp_str, 1) == EXIT_FAILURE) 336 | { 337 | return POLARITY_ERROR; 338 | } 339 | 340 | if (strncmp(tmp_str, "i", 1) == 0) 341 | { 342 | polarity = INVERSED; 343 | } 344 | else if (strncmp(tmp_str, "n", 1) == 0) 345 | { 346 | polarity = NORMAL; 347 | } 348 | else 349 | { 350 | polarity = POLARITY_ERROR; 351 | } 352 | 353 | if (polarity >= 0) 354 | { 355 | libsoc_pwm_debug(__func__, pwm->chip, pwm->pwm, "got polarity as %s", pwm_polarity_strings[polarity]); 356 | } 357 | else 358 | { 359 | libsoc_pwm_debug(__func__, pwm->chip, pwm->pwm, "getting polarity failed"); 360 | } 361 | 362 | return polarity; 363 | } 364 | 365 | -------------------------------------------------------------------------------- /lib/spi.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: LGPL-2.1-only */ 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include "libsoc_spi.h" 15 | #include "libsoc_debug.h" 16 | #include "libsoc_file.h" 17 | 18 | void 19 | libsoc_spi_debug (const char *func, spi * spi, char *format, ...) 20 | { 21 | #ifdef DEBUG 22 | 23 | if (libsoc_get_debug ()) 24 | { 25 | va_list args; 26 | 27 | fprintf (stderr, "libsoc-spi-debug: "); 28 | 29 | va_start (args, format); 30 | vfprintf (stderr, format, args); 31 | va_end (args); 32 | 33 | if (spi == NULL) 34 | { 35 | fprintf (stderr, " (NULL, %s)", func); 36 | } 37 | else 38 | { 39 | fprintf (stderr, " (spidev%d.%d, %s)", spi->spi_dev, 40 | spi->chip_select, func); 41 | } 42 | 43 | fprintf (stderr, "\n"); 44 | } 45 | #endif 46 | } 47 | 48 | spi * 49 | libsoc_spi_init (uint16_t spidev_device, uint8_t chip_select) 50 | { 51 | spi *spi_dev; 52 | 53 | libsoc_spi_debug (__func__, NULL, "initialising spidev device %d.%d", 54 | spidev_device, chip_select); 55 | 56 | spi_dev = malloc (sizeof (spi)); 57 | 58 | if (spi_dev == NULL) 59 | { 60 | libsoc_spi_debug (__func__, NULL, "failed to allocate memory"); 61 | return NULL; 62 | } 63 | 64 | char path[40]; 65 | 66 | spi_dev->spi_dev = spidev_device; 67 | spi_dev->chip_select = chip_select; 68 | 69 | sprintf (path, "/dev/spidev%d.%d", spi_dev->spi_dev, spi_dev->chip_select); 70 | 71 | if (!file_valid (path)) 72 | { 73 | libsoc_spi_debug (__func__, spi_dev, "%s not a vaild device", path); 74 | goto error; 75 | } 76 | 77 | spi_dev->fd = file_open (path, O_SYNC | O_RDWR); 78 | 79 | if (spi_dev->fd < 0) 80 | { 81 | libsoc_spi_debug (__func__, spi_dev, "%s could not be opened", path); 82 | goto error; 83 | } 84 | 85 | return spi_dev; 86 | 87 | error: 88 | 89 | free (spi_dev); 90 | 91 | return NULL; 92 | } 93 | 94 | int 95 | libsoc_spi_set_bits_per_word (spi * spi, spi_bpw bpw) 96 | { 97 | if (bpw != BITS_8 && bpw != BITS_16) 98 | { 99 | libsoc_spi_debug (__func__, spi, "bits per word was not BITS_8" 100 | " or BITS_16", bpw); 101 | return EXIT_FAILURE; 102 | } 103 | 104 | libsoc_spi_debug (__func__, spi, "setting bits per word to %d", bpw); 105 | 106 | int ret = ioctl (spi->fd, SPI_IOC_WR_BITS_PER_WORD, &bpw); 107 | 108 | if (ret == -1) 109 | { 110 | libsoc_spi_debug (__func__, spi, "failed setting bits per word"); 111 | return EXIT_FAILURE; 112 | } 113 | 114 | return EXIT_SUCCESS; 115 | } 116 | 117 | spi_bpw 118 | libsoc_spi_get_bits_per_word (spi * spi) 119 | { 120 | uint8_t bpw; 121 | 122 | int ret = ioctl (spi->fd, SPI_IOC_RD_BITS_PER_WORD, &bpw); 123 | 124 | if (ret == -1) 125 | { 126 | libsoc_spi_debug (__func__, spi, "failed reading bits per word"); 127 | return BPW_ERROR; 128 | } 129 | 130 | switch (bpw) 131 | { 132 | case 8: 133 | libsoc_spi_debug (__func__, spi, "read bits per word as 8"); 134 | return BITS_8; 135 | case 16: 136 | libsoc_spi_debug (__func__, spi, "read bits per word as 16"); 137 | return BITS_16; 138 | default: 139 | libsoc_spi_debug (__func__, spi, "bits per word not recognised"); 140 | return BPW_ERROR; 141 | } 142 | } 143 | 144 | int 145 | libsoc_spi_set_speed (spi * spi, uint32_t speed) 146 | { 147 | libsoc_spi_debug (__func__, spi, "setting speed to %dHz", speed); 148 | 149 | int ret = ioctl (spi->fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed); 150 | 151 | if (ret == -1) 152 | { 153 | libsoc_spi_debug (__func__, spi, "failed setting speed"); 154 | return EXIT_FAILURE; 155 | } 156 | 157 | return EXIT_SUCCESS; 158 | } 159 | 160 | uint32_t 161 | libsoc_spi_get_speed (spi * spi) 162 | { 163 | uint32_t speed; 164 | 165 | int ret = ioctl (spi->fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed); 166 | 167 | if (ret == -1) 168 | { 169 | libsoc_spi_debug (__func__, spi, "failed reading speed"); 170 | return -1; 171 | } 172 | 173 | libsoc_spi_debug (__func__, spi, "read speed as %dHz", speed); 174 | 175 | return speed; 176 | } 177 | 178 | int 179 | libsoc_spi_set_mode (spi * spi, spi_mode mode) 180 | { 181 | if (spi == NULL) 182 | { 183 | libsoc_spi_debug (__func__, NULL, "spi was not valid"); 184 | return EXIT_FAILURE; 185 | } 186 | 187 | libsoc_spi_debug (__func__, spi, "setting mode to %d", mode); 188 | 189 | uint8_t new_mode; 190 | 191 | switch (mode) 192 | { 193 | case MODE_0: 194 | new_mode = SPI_MODE_0; 195 | break; 196 | case MODE_1: 197 | new_mode = SPI_MODE_1; 198 | break; 199 | case MODE_2: 200 | new_mode = SPI_MODE_2; 201 | break; 202 | case MODE_3: 203 | new_mode = SPI_MODE_3; 204 | break; 205 | default: 206 | return EXIT_FAILURE; 207 | } 208 | 209 | int ret = ioctl (spi->fd, SPI_IOC_WR_MODE, &new_mode); 210 | 211 | if (ret == -1) 212 | { 213 | libsoc_spi_debug (__func__, spi, "failed setting mode"); 214 | return EXIT_FAILURE; 215 | } 216 | 217 | return EXIT_SUCCESS; 218 | } 219 | 220 | spi_mode 221 | libsoc_spi_get_mode (spi * spi) 222 | { 223 | uint8_t mode; 224 | 225 | if (spi == NULL) 226 | { 227 | libsoc_spi_debug (__func__, NULL, "spi was not valid"); 228 | return MODE_ERROR; 229 | } 230 | 231 | int ret = ioctl (spi->fd, SPI_IOC_RD_MODE, &mode); 232 | 233 | if (ret == -1) 234 | { 235 | libsoc_spi_debug (__func__, spi, "failed reading mode"); 236 | return MODE_ERROR; 237 | } 238 | 239 | switch (mode) 240 | { 241 | case SPI_MODE_0: 242 | libsoc_spi_debug (__func__, spi, "read mode as 0"); 243 | return MODE_0; 244 | case SPI_MODE_1: 245 | libsoc_spi_debug (__func__, spi, "read mode as 1"); 246 | return MODE_1; 247 | case SPI_MODE_2: 248 | libsoc_spi_debug (__func__, spi, "read mode as 2"); 249 | return MODE_2; 250 | case SPI_MODE_3: 251 | libsoc_spi_debug (__func__, spi, "read mode as 3"); 252 | return MODE_3; 253 | default: 254 | libsoc_spi_debug (__func__, spi, "mode not recognised"); 255 | return MODE_ERROR; 256 | } 257 | } 258 | 259 | int 260 | libsoc_spi_write (spi * spi, uint8_t * tx, uint32_t len) 261 | { 262 | libsoc_spi_debug (__func__, spi, "performing write transfer of %d bytes", 263 | len); 264 | 265 | if (spi == NULL || tx == NULL) 266 | { 267 | libsoc_spi_debug (__func__, spi, "spi or tx was NULL"); 268 | return EXIT_FAILURE; 269 | } 270 | 271 | if (len <= 0) 272 | { 273 | libsoc_spi_debug (__func__, spi, "length was less than zero"); 274 | return EXIT_FAILURE; 275 | } 276 | 277 | int ret; 278 | 279 | struct spi_ioc_transfer tr = { 280 | .tx_buf = (unsigned long) tx, 281 | .len = len, 282 | }; 283 | 284 | ret = ioctl (spi->fd, SPI_IOC_MESSAGE (1), &tr); 285 | 286 | if (ret < 1) 287 | { 288 | libsoc_spi_debug (__func__, spi, "failed sending message"); 289 | return EXIT_FAILURE; 290 | } 291 | 292 | return EXIT_SUCCESS; 293 | } 294 | 295 | int 296 | libsoc_spi_read (spi * spi, uint8_t * rx, uint32_t len) 297 | { 298 | libsoc_spi_debug (__func__, spi, "performing read transfer of %d bytes", 299 | len); 300 | 301 | if (spi == NULL || rx == NULL) 302 | { 303 | libsoc_spi_debug (__func__, spi, "spi or rx was NULL"); 304 | return EXIT_FAILURE; 305 | } 306 | 307 | if (len <= 0) 308 | { 309 | libsoc_spi_debug (__func__, spi, "length was less than zero"); 310 | return EXIT_FAILURE; 311 | } 312 | 313 | int ret; 314 | 315 | struct spi_ioc_transfer tr = { 316 | .rx_buf = (unsigned long) rx, 317 | .len = len, 318 | }; 319 | 320 | ret = ioctl (spi->fd, SPI_IOC_MESSAGE (1), &tr); 321 | 322 | if (ret < 1) 323 | { 324 | libsoc_spi_debug (__func__, spi, "failed recieving message"); 325 | return EXIT_FAILURE; 326 | } 327 | 328 | return EXIT_SUCCESS; 329 | } 330 | 331 | int 332 | libsoc_spi_rw (spi * spi, uint8_t * tx, uint8_t * rx, uint32_t len) 333 | { 334 | libsoc_spi_debug (__func__, spi, 335 | "performing duplex rw transfer of %d bytes", len); 336 | 337 | if (spi == NULL || rx == NULL || tx == NULL) 338 | { 339 | libsoc_spi_debug (__func__, spi, "spi | rx | tx was NULL"); 340 | return EXIT_FAILURE; 341 | } 342 | 343 | if (len <= 0) 344 | { 345 | libsoc_spi_debug (__func__, spi, "length was less than zero"); 346 | return EXIT_FAILURE; 347 | } 348 | 349 | int ret; 350 | 351 | struct spi_ioc_transfer tr = { 352 | .rx_buf = (unsigned long) rx, 353 | .tx_buf = (unsigned long) tx, 354 | .len = len, 355 | }; 356 | 357 | ret = ioctl (spi->fd, SPI_IOC_MESSAGE (1), &tr); 358 | 359 | if (ret < 1) 360 | { 361 | libsoc_spi_debug (__func__, spi, "failed duplex transfer"); 362 | return EXIT_FAILURE; 363 | } 364 | 365 | return EXIT_SUCCESS; 366 | } 367 | 368 | int 369 | libsoc_spi_free (spi * spi) 370 | { 371 | if (spi == NULL) 372 | { 373 | libsoc_spi_debug (__func__, NULL, "spi was not valid"); 374 | return EXIT_FAILURE; 375 | } 376 | 377 | libsoc_spi_debug (__func__, spi, "freeing spi device"); 378 | 379 | if (file_close (spi->fd) < 0) 380 | return EXIT_FAILURE; 381 | 382 | free (spi); 383 | 384 | return EXIT_SUCCESS; 385 | } 386 | -------------------------------------------------------------------------------- /libsoc.pc.in: -------------------------------------------------------------------------------- 1 | prefix=@prefix@ 2 | exec_prefix=@exec_prefix@ 3 | libdir=@libdir@ 4 | includedir=@includedir@ 5 | 6 | Name: soc 7 | Description: SoC peripherals library 8 | Version: @VERSION@ 9 | Libs: -L${libdir} -lsoc 10 | Cflags: -I${includedir} 11 | -------------------------------------------------------------------------------- /roadmap/TODO: -------------------------------------------------------------------------------- 1 | - Investigate using pthread_barrier_wait with GPIO 2 | - Investigate using pread for improved GPIO throughput and polling 3 | 4 | - ADC Support 5 | - See file ADC 6 | 7 | - UART Support 8 | 9 | - SPI 10 | - Add support for more SPI bus config FLAGS 11 | 12 | - GPIO 13 | - Support for setting multiple GPIO's 14 | 15 | - I2C 16 | - Look at using unsigned long to hold spi rw data 17 | - Support single register read write, similar to: 18 | - http://bunniestudios.com/blog/images/infocast_i2c.c 19 | -------------------------------------------------------------------------------- /roadmap/adc: -------------------------------------------------------------------------------- 1 | Ordered Texas Instruments LM19CIZ Temperature Sensor to do ADC testing 2 | 3 | Unit tests will be reading the adc and displaying temperatures values 4 | -------------------------------------------------------------------------------- /static-docs/.gitignore: -------------------------------------------------------------------------------- 1 | site/ 2 | -------------------------------------------------------------------------------- /static-docs/README: -------------------------------------------------------------------------------- 1 | These files are the static content and configuration for the mkdocs 2 | documentation deployment on http://jackmitch.github.io/libsoc. 3 | 4 | To build the docs yo umust first install the mkdocs python package and 5 | mkdocs cinder theme. These can be installed via pip. 6 | 7 | pip install mkdocs mkdocs-cinder 8 | 9 | The documentation can be served locally from this directory using the 10 | command 11 | 12 | mkdocs serve 13 | 14 | To add documentation create a pull request and it will be built and 15 | deployed at the next release, or sooner if it is just changes to current 16 | API documentation or features. 17 | -------------------------------------------------------------------------------- /static-docs/docs/.gitignore: -------------------------------------------------------------------------------- 1 | site/ 2 | -------------------------------------------------------------------------------- /static-docs/docs/c/debug.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jackmitch/libsoc/545b354968a9d03008e1e86e14c58e3f8423a20c/static-docs/docs/c/debug.md -------------------------------------------------------------------------------- /static-docs/docs/c/gpio.md: -------------------------------------------------------------------------------- 1 | # GPIO 2 | 3 | --- 4 | 5 | ## Data Types 6 | --- 7 | ### gpio_mode 8 | 9 | Determines the way in which libsoc handles exporting and unexporting 10 | GPIOs in the Linux subsystem. 11 | 12 | * **LS_GPIO_SHARED** 13 | 14 | if the gpio is already exported then it will not unexport 15 | the GPIO on free. If it is not exported, then it will 16 | unexport on free. 17 | 18 | * **LS_GPIO_GREEDY** 19 | 20 | will succeed if the GPIO is already exported, but will 21 | always unexport the GPIO on free. 22 | 23 | * **LS_GPIO_WEAK** 24 | 25 | will fail if GPIO is already exported, will always unexport 26 | on free. 27 | 28 | --- 29 | 30 | ### gpio_direction 31 | 32 | Used for setting and reading the direction of the GPIO pin. 33 | 34 | * **DIRECTION_ERROR** 35 | 36 | Returned when the GPIO direction could not be read 37 | 38 | * **INPUT** 39 | 40 | GPIO input mode, it's input value can be read 41 | 42 | * **OUTPUT** 43 | 44 | GPIO output mode, it's output value can be written 45 | 46 | --- 47 | 48 | ### gpio_level 49 | 50 | Used for setting and reading the level of the GPIO pin. 51 | 52 | * **LEVEL_ERROR** 53 | 54 | Returned when the GPIO level could not be read 55 | 56 | * **LOW** 57 | 58 | GPIO value low, usually logic 0 on the pin, but could be 1 if 59 | the gpio is inverted. 60 | 61 | * **HIGH** 62 | 63 | GPIO value high, usually logic 1 on the pin, but could be 0 if 64 | the gpio is inverted. 65 | 66 | --- 67 | 68 | ### gpio_edge 69 | 70 | Used for setting and reading the edge of the GPIO pin. 71 | 72 | * **EDGE_ERROR** 73 | 74 | Returned when the GPIO edge could not be read 75 | 76 | * **RISING** 77 | 78 | GPIO interrupt is triggered on a rising edge, e.g. logic level 79 | 0 followed by 1 80 | 81 | * **FALLING** 82 | 83 | GPIO interrupt is triggered on a falling edge, e.g. logic level 84 | 1 followed by 0 85 | 86 | * **NONE** 87 | 88 | GPIO interrupt edge is not set 89 | 90 | * **BOTH** 91 | 92 | GPIO interrupt is triggered on both a falling and rising edge 93 | 94 | --- 95 | 96 | ### gpio_int_ret 97 | 98 | Return type for blocked GPIO interrupts. 99 | 100 | * **LS_INT_ERROR** 101 | 102 | Error condition 103 | 104 | * **LS_INT_TRIGGERED** 105 | 106 | Interrupt was triggered 107 | 108 | * **LS_INT_TIMEOUT** 109 | 110 | GPIO poll timedout 111 | 112 | ## Functions 113 | --- 114 | ### libsoc_gpio_request 115 | 116 | ```C 117 | gpio * libsoc_gpio_request(unsigned int gpio_id, gpio_mode mode) 118 | ``` 119 | 120 | - *unsigned int* **gpio_id** 121 | 122 | the Linux ID number for the GPIO you wish to use 123 | 124 | - *[gpio_mode](#gpio_mode)* **mode** 125 | 126 | the mode in which libsoc handles the GPIO file descriptor 127 | 128 | Request a GPIO by it's Linux ID number and set the [gpio_mode](#gpio_mode) 129 | under which libsoc will hold the file descriptor. Returns a malloced gpio struct 130 | which will need to be freed by [libsoc_gpio_free](#libsoc_gpio_free) when no 131 | longer needed. 132 | 133 | Returns `NULL` on failure. 134 | 135 | --- 136 | 137 | ### libsoc_gpio_free 138 | 139 | ```c 140 | int libsoc_gpio_free(gpio * gpio) 141 | ``` 142 | 143 | - *gpioi\** **gpio** 144 | 145 | the previously requested gpio that you wish to release 146 | 147 | Free the memory associated with a previously requested GPIO and close the file 148 | descriptors. 149 | 150 | Returns `EXIT_SUCCESS`/`EXIT_FAILURE` 151 | 152 | --- 153 | 154 | ### libsoc_gpio_set_direction 155 | 156 | ```c 157 | int libsoc_gpio_set_direction(gpio * current_gpio, gpio_direction direction) 158 | ``` 159 | 160 | - *gpio\** **current_gpio** 161 | 162 | requested gpio that you wish to set the direction of 163 | 164 | - *[gpio_direction](#gpio_direction)* **direction** 165 | 166 | direction you wish to set the gpio to 167 | 168 | Set the direction of a GPIO, `INPUT` for reading a GPIO, `OUTPUT` for setting a 169 | GPIO. 170 | 171 | Returns `EXIT_SUCCESS`/`EXIT_FAILURE` 172 | 173 | --- 174 | ### libsoc_gpio_get_direction 175 | 176 | ```c 177 | gpio_direction libsoc_gpio_get_direction(gpio * current_gpio) 178 | ``` 179 | 180 | - *gpio\** **current_gpio** 181 | 182 | requested gpio that you wish to get the direction of 183 | 184 | Get the current [gpio_direction](#gpio_direction) of a requested GPIO. 185 | 186 | Returns [gpio_direction](#gpio_direction), `DIRECTION_ERROR` on failure, 187 | `INPUT`/`OUTPUT` on success. 188 | 189 | --- 190 | ### libsoc_gpio_set_level 191 | 192 | ```c 193 | int libsoc_gpio_set_level(gpio * current_gpio, gpio_level level) 194 | ``` 195 | 196 | - *gpio \** **current_gpio** 197 | 198 | requested gpio you wish to set the level of 199 | 200 | - *[gpio_level](#gpio_level)* **level** 201 | 202 | level you wish to set the gpio to 203 | 204 | Set the output level of a requested GPIO to `HIGH` or `LOW`. 205 | 206 | 207 | Returns `EXIT_SUCCESS`/`EXIT_FAILURE` 208 | 209 | --- 210 | ### libsoc_gpio_get_level 211 | 212 | ```c 213 | gpio_level libsoc_gpio_get_level(gpio * current_gpio) 214 | ``` 215 | 216 | - *gpio \** **current_gpio** 217 | 218 | requested gpio you wish to get the level of 219 | 220 | Get the current [gpio_level](#gpio_level) of a requested GPIO. 221 | 222 | Returns [gpio_level](#gpio_level), `LEVEL_ERROR` on failure, 223 | `LOW`/`HIGH` on success. 224 | 225 | --- 226 | ### libsoc_gpio_set_edge 227 | 228 | ```c 229 | int libsoc_gpio_set_edge(gpio * current_gpio, gpio_edge edge) 230 | ``` 231 | 232 | - *gpio \** **current_gpio** 233 | 234 | requested gpio you wish to set the edge of 235 | 236 | - *[gpio_edge](#gpio_edge)* **edge** 237 | 238 | edge you wish to set the gpio to 239 | 240 | Set the edge type of a requested GPIO. The edge is the type of signal 241 | change that will trigger interrupt detection. See [gpio_edge](#gpio_edge) 242 | for explanations of the different types of edges and how they work. 243 | 244 | Returns `EXIT_SUCCESS`/`EXIT_FAILURE` 245 | 246 | --- 247 | 248 | ### libsoc_gpio_get_edge 249 | 250 | ```c 251 | gpio_edge libsoc_gpio_get_edge(gpio * current_gpio) 252 | ``` 253 | 254 | - *gpio \** **current_gpio** 255 | 256 | requested gpio you wish to get the edge of 257 | 258 | Get the current [gpio_edge](#gpio_edge) of a requested GPIO. 259 | 260 | Returns [gpio_edge](#gpio_edge), `EDGE_ERROR` on failure, 261 | `RISING`/`FALLING`/`BOTH`/`NONE` on success. 262 | 263 | --- 264 | ### libsoc_gpio_wait_interrupt 265 | 266 | ```c 267 | int libsoc_gpio_wait_interrupt(gpio * gpio, int timeout) 268 | ``` 269 | 270 | - *gpio \** **gpio** 271 | 272 | requested gpio you wish to wait for an interrupt on 273 | 274 | - *int* **timeout** 275 | 276 | the number of seconds to wait for the interrupt, -1 for block indefinitly 277 | 278 | Block for a set amount of seconds (or indefinitly) waiting for an interrupt on a 279 | GPIO to occur. If you wish to use a non-blocking interrupt mechanism see 280 | [libsoc_gpio_callback_interrupt](#libsoc_gpio_callback_interrupt). 281 | 282 | Returns `LS_INT_ERROR` on failure, `LS_INT_TRIGGERED` on captured interrupt, 283 | `LS_INT_TIMEOUT` if no interrupt was captured in the specified time. 284 | 285 | --- 286 | ### libsoc_gpio_callback_interrupt 287 | 288 | ```c 289 | int libsoc_gpio_callback_interrupt(gpio * gpio, int (*callback_fn) (void *), void *arg) 290 | ``` 291 | 292 | - *gpio \** **gpio** 293 | 294 | requested gpio you wish to set an interrupt handler for 295 | 296 | - *int (\*callback_fn) (void \*)* **function** 297 | 298 | name of the function to use as the interrupt handler. Must match the prototype 299 | `int* function(void* ptr)` 300 | 301 | - *void \** **arg** 302 | 303 | void casted pointer you wish to be passed to your interrupt handler 304 | 305 | Setup an interrupt handler on a GPIO. This will start a new pthread with an infinite poll 306 | on the GPIO waiting for the interrupt. When an interrupt is detected the supplied function 307 | will run in the thread, and then return to waiting for an interrupt. 308 | 309 | Only one interrupt will be queued if it arrives while your supplied function is being run, 310 | so it is possible to miss interrupts if they happen too fast. 311 | 312 | Returns `EXIT_SUCCESS`/`EXIT_FAILURE` 313 | 314 | --- 315 | ### libsoc_gpio_callback_interrupt_cancel 316 | 317 | ```c 318 | int libsoc_gpio_callback_interrupt_cancel(gpio * gpio) 319 | ``` 320 | 321 | - *gpio \** **gpio** 322 | 323 | the gpio on which to cancel a waiting interrupt handler 324 | 325 | Cancel a previously set interrupt handler on a GPIO. This uses the pthread_cancel function, 326 | so it may cancel mid way through your interrupt handler function. 327 | 328 | Returns `EXIT_SUCCESS`/`EXIT_FAILURE` 329 | -------------------------------------------------------------------------------- /static-docs/docs/c/i2c.md: -------------------------------------------------------------------------------- 1 | # I2C 2 | --- 3 | ## Functions 4 | --- 5 | ### libsoc_i2c_init 6 | 7 | ```c 8 | i2c* libsoc_i2c_init (uint8_t i2c_bus, uint8_t i2c_address) 9 | ``` 10 | 11 | - *uint8_t* **i2c_bus** 12 | 13 | the linux enumerated bus number 14 | 15 | - *uint8_t* **i2c_address** 16 | 17 | the peripherals address on the i2c bus 18 | 19 | Initialises a new i2c instance at the specificed address. Returns a 20 | malloced i2c struct which must be freed with 21 | [libsoc_i2c_free](#libsoc_i2c_free) when no longer needed. 22 | 23 | Returns `NULL` on failure. 24 | 25 | --- 26 | 27 | ### libsoc_i2c_free 28 | 29 | ```c 30 | int libsoc_i2c_free (i2c * i2c) 31 | ``` 32 | 33 | - *i2c\** **i2c** 34 | 35 | previously initialised i2c struct 36 | 37 | Free the memory associated with a previously initialised i2c struct and release 38 | the hold on the i2c address. 39 | 40 | Returns `EXIT_SUCCESS` or `EXIT_FAILURE` 41 | 42 | --- 43 | 44 | ### libsoc_i2c_write 45 | 46 | ```c 47 | int libsoc_i2c_write (i2c * i2c, uint8_t * buffer, uint16_t len) 48 | ``` 49 | 50 | - *i2c\** **i2c** 51 | 52 | previously initialised i2c struct 53 | 54 | - *uint8_t\** **buffer** 55 | 56 | pointer to output data buffer 57 | 58 | - *uint16_t* **len** 59 | 60 | length of data to write in bytes 61 | 62 | Write `len` bytes starting from the `buffer` data pointer to the specified 63 | i2c device. 64 | 65 | 66 | Returns `EXIT_SUCCESS` or `EXIT_FAILURE` 67 | 68 | --- 69 | 70 | ### libsoc_i2c_read 71 | 72 | ```c 73 | int libsoc_i2c_read (i2c * i2c, uint8_t * buffer, uint16_t len) 74 | ``` 75 | 76 | - *i2c\** **i2c** 77 | 78 | previously initialised i2c struct 79 | 80 | - *uint8_t\** **buffer** 81 | 82 | pointer to input data buffer 83 | 84 | - *uint16_t* **len** 85 | 86 | length of data to read in bytes 87 | 88 | Read `len` bytes into the `buffer` data pointer from the specified 89 | i2c device. 90 | 91 | Returns `EXIT_SUCCESS` or `EXIT_FAILURE` 92 | 93 | --- 94 | 95 | ### libsoc_i2c_set_timeout 96 | 97 | ```c 98 | int libsoc_i2c_set_timeout(i2c * i2c, int timeout) 99 | ``` 100 | 101 | - *i2c\** **i2c** 102 | 103 | previously initialised i2c struct 104 | 105 | - *int* **timeout** 106 | 107 | i2c timeout in milliseconds/10 108 | 109 | Set the timeout of a i2c device in milliseconds/10. For example if a timeout of 110 | 20ms is requred, `timeout` would be set to 2. 111 | 112 | ```c 113 | // 20ms timeout, 2*10ms 114 | libsoc_i2c_set_timeout(device, 2); 115 | ``` 116 | 117 | Returns `EXIT_SUCCESS` or `EXIT_FAILURE` 118 | 119 | -------------------------------------------------------------------------------- /static-docs/docs/c/pwm.md: -------------------------------------------------------------------------------- 1 | # PWM 2 | --- 3 | ## Data Types 4 | --- 5 | ### shared_mode 6 | 7 | Determines the way in which libsoc handles exporting and unexporting 8 | PWMs in the Linux subsystem. 9 | 10 | * **LS_PWM_SHARED** 11 | 12 | if the pwm is already exported then it will not unexport 13 | the pwm on free. If it is not exported, then it will 14 | unexport on free. 15 | 16 | * **LS_PWM_GREEDY** 17 | 18 | will succeed if the pwm is already exported, but will 19 | always unexport the pwm on free. 20 | 21 | * **LS_PWM_WEAK** 22 | 23 | will fail if pwm is already exported, will always unexport 24 | on free. 25 | 26 | ### pwm_enabled 27 | 28 | Used for setting and reading the enabled state of the PWM device 29 | 30 | * **ENABLED_ERROR** 31 | 32 | Returned when the enabled state could not be read 33 | 34 | * **DISABLED** 35 | 36 | PWM disabled mode, the pwm is not currently running 37 | 38 | * **ENABLED** 39 | 40 | PWM enabled mode, the pwm is currently running 41 | 42 | --- 43 | 44 | ### pwm_polarity 45 | 46 | Used for setting and reading the polarity of the PWM device 47 | 48 | * **POLARITY_ERROR** 49 | 50 | Returned when the polarity could not be read 51 | 52 | * **NORMAL** 53 | 54 | Polarity mode is normal 55 | 56 | * **INVERSED** 57 | 58 | Polarity mode is inversed 59 | 60 | ## Functions 61 | --- 62 | ### libsoc_pwm_request 63 | 64 | ```c 65 | pwm* libsoc_pwm_request(unsigned int pwm_chip, unsigned int pwm_num, enum shared_mode mode) 66 | ``` 67 | 68 | - *unsigned int* **pwm_chip** 69 | 70 | the pwm chip number which controls the pwm you wish to use 71 | 72 | - *unsigned int* **pwm_num** 73 | 74 | the pwm number within your specified pwm chip 75 | 76 | - *shared_mode* **mode** 77 | 78 | the mode in which libsoc handles the PWM file descriptor 79 | 80 | Request a pwm by specifying its pwm chip number and the pwm number it is on that chip. 81 | Set [shared_mode](#shared_mode) to handle how libsoc manages the file descriptor. 82 | Returns a malloced pwm struct which will need to be freed by [libsoc_pwm_free](#libsoc_pwm_free) 83 | when no longer needed. 84 | 85 | --- 86 | 87 | ### libsoc_pwm_free 88 | 89 | ```c 90 | int libsoc_pwm_free(pwm *pwm) 91 | ``` 92 | 93 | - *pwm\** **pwm** 94 | 95 | the previously requested pwm that you wish to release 96 | 97 | Free the memory associated with a previously requested PWM device and close the file 98 | descriptors. 99 | 100 | --- 101 | 102 | ### libsoc_pwm_set_enabled 103 | 104 | ```c 105 | int libsoc_pwm_set_enabled(pwm *pwm, pwm_enabled enabled) 106 | ``` 107 | 108 | - *pwm\** **pwm** 109 | 110 | requested pwm that you wish to set enabled/disabled 111 | 112 | - *[pwm_enabled](#pwm_enabled)* **enabled** 113 | 114 | state you wish to set the pwm device to 115 | 116 | Set the state of a PWM device, `ENABLED` to enable to the device, `DISABLED` to 117 | disable the device. 118 | 119 | --- 120 | 121 | ### libsoc_pwm_get_enabled 122 | 123 | ```c 124 | pwm_enabled libsoc_pwm_get_enabled(pwm *pwm) 125 | ``` 126 | 127 | - *pwm\** **pwm** 128 | 129 | requested pwm that you wish to get the state of 130 | 131 | Get the current [pwm_enabled](#pwm_enabled) state of a requested PWM device. 132 | 133 | --- 134 | 135 | ### libsoc_pwm_set_period 136 | 137 | ```c 138 | int libsoc_pwm_set_period(pwm *pwm, unsigned int period) 139 | ``` 140 | 141 | - *pwm\** **pwm** 142 | 143 | requested pwm that you wish to set the period of 144 | 145 | - *unsigned int* **period** 146 | 147 | the total period of the pwm signal in nanoseconds 148 | 149 | Set the period of a PWM device, the value is specified in nanoseconds and is the sum 150 | of the active and inactive time of the signal. 151 | 152 | --- 153 | 154 | ### libsoc_pwm_get_period 155 | 156 | ```c 157 | int libsoc_pwm_get_period(pwm *pwm) 158 | ``` 159 | 160 | - *pwm\** **pwm** 161 | 162 | requested pwm that you wish to get the period of 163 | 164 | Get the currently set perioid of the PWM device in nanoseconds. 165 | 166 | --- 167 | 168 | ### libsoc_pwm_set_duty_cycle 169 | 170 | ```c 171 | int libsoc_pwm_set_duty_cycle(pwm *pwm, unsigned int duty) 172 | ``` 173 | 174 | - *pwm\** **pwm** 175 | 176 | requested pwm that you wish to set the duty cycle of 177 | 178 | - *unsigned int* **duty** 179 | 180 | the duty cycle in nanoseconds 181 | 182 | 183 | Set the duty cycle of the specified PWM device in nanoseconds. The duty cycle is the 184 | active time of the PWM signal and must be less than the period. 185 | 186 | --- 187 | 188 | ### libsoc_pwm_get_duty_cycle 189 | 190 | ```c 191 | int libsoc_pwm_get_duty_cycle(pwm *pwm) 192 | ``` 193 | 194 | - *pwm\** **pwm** 195 | 196 | requested pwm that you wish to get the duty cycle of 197 | 198 | Get the currently set duty cycle of a requested PWM device in nanoseconds. 199 | 200 | --- 201 | 202 | ### libsoc_pwm_set_polarity 203 | 204 | ```c 205 | int libsoc_pwm_set_polarity(pwm *pwm, pwm_polarity polarity) 206 | ``` 207 | 208 | - *pwm\** **pwm** 209 | 210 | requested pwm that you wish to set the polarity of 211 | 212 | - *pwm_polarity* **polarity** 213 | 214 | polarity you wish to set the pwm device to 215 | 216 | Set the polarity of a PWM device, `NORMAL` will give you the default polarity, 217 | `INVERSED` will give you the inverse polarity of normal. 218 | 219 | Polarity support is optional, ensure your PWM devices kernel driver is capable before 220 | relying on this support. The value -1 will be returned on failure to set the polarity. 221 | 222 | --- 223 | 224 | ### libsoc_pwm_get_polarity 225 | 226 | ```c 227 | pwm_polarity libsoc_pwm_get_polarity(pwm *pwm) 228 | ``` 229 | 230 | - *pwm\** **pwm** 231 | 232 | requested pwm that you wish to get the polarity of 233 | 234 | Get the current [pwm_polarity](#pwm_polarity) of a requested PWM device. 235 | 236 | --- 237 | 238 | -------------------------------------------------------------------------------- /static-docs/docs/c/spi.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jackmitch/libsoc/545b354968a9d03008e1e86e14c58e3f8423a20c/static-docs/docs/c/spi.md -------------------------------------------------------------------------------- /static-docs/docs/index.md: -------------------------------------------------------------------------------- 1 | ## Introduction 2 | 3 | --- 4 | 5 | ### What is libsoc 6 | 7 | libsoc is a C library to interface with common peripherals found in 8 | System on Chips (SoC) through generic Linux Kernel interfaces. 9 | 10 | It is aimed at new Linux users, and intends to be a stepping stone to 11 | enable a user to get started quickly. It is optimised for reliability 12 | rather than speed. While the library should be fast, no guarantees are 13 | made on its determinism and it should not be used in time critical 14 | routines. 15 | 16 | ### Why libsoc 17 | 18 | libsoc was born due to the influx of new embedded Linux boards becoming 19 | available cheap, and to hobbyists. There are currently numerous 20 | libraries that do interfacing with common SoC peripherals, but they all 21 | tend to be centred around a particular board or SoC. This leads to board 22 | specific hacks and in some cases direct bypassing of the Linux Kernel. 23 | 24 | libsoc aims to be generic and compatible with any SoC that has drivers 25 | exposing the correct interfaces for the defined peripheral. 26 | 27 | ## Support 28 | 29 | --- 30 | 31 | ### SoC Support 32 | 33 | If your SoC exposes its I/O subsystems using the generic Linux kernel 34 | interfaces then yes, libsoc supports your SoC! 35 | 36 | ### Language Support 37 | 38 | The library is written in C and has a native C API. A subset of the API 39 | is also supported with Python bindings. 40 | 41 | #### [C API](http://jackmitch.github.io/libsoc/c/gpio) 42 | 43 | - Manual GPIO Manipulation through sysfs (Value, Edge, Direction, Exporting) 44 | - Blocking GPIO Interrupts with timeout 45 | - Non-blocking GPIO Interrupts with callback mechanism (pthread based) 46 | - SPI transfers using spidev 47 | - I2C transfers using ioctls 48 | - PWM support through sysfs (Linux 3.12+) 49 | - Automatic board probing via installed config files 50 | 51 | #### [Python Bindings](http://jackmitch.github.io/libsoc/python) 52 | 53 | - Manual GPIO Manipulation through sysfs (Value, Edge, Direction, Exporting) 54 | - Blocking GPIO Interrupts with timeout 55 | - Non-blocking GPIO Interrupts with callback mechanism 56 | - I2C transfers 57 | 58 | ## Building 59 | 60 | --- 61 | 62 | libsoc is built and installed using the autotools build system. This means it 63 | follows the traditional linux methodology of autoreconf, configure, make. 64 | 65 | First, check if your distro packages libsoc. If it does it is easiest to install 66 | your distro's version of libsoc through its provided package manager. Depending 67 | on your distro this may be `apt-get`, `dnf`, `yum`, `pacman`, etc. Consult your 68 | distro documentation for more info. 69 | 70 | ### Manually Building 71 | 72 | First, make sure you have the prerequisites installed. Under Debian Jessie this 73 | means: 74 | 75 | * `autoconf` 76 | * `build-essential` 77 | * `libtool-bin` 78 | * `pkg-config` 79 | * `python-dev` * 80 | * `python3-dev` ** 81 | 82 | Under Fedora this would instead be: 83 | 84 | * `autoconf` 85 | * `automake` 86 | * `libtool` 87 | * `python2-devel` * 88 | * `python3-devel` ** 89 | 90 | \* Optional, only required if Python 2 bindings are desired.
91 | \*\* Optional, only required if Python 3 bindings are desired. 92 | 93 | Then, clone libsoc from its git repository. 94 | 95 | git clone https://github.com/jackmitch/libsoc.git libsoc.git 96 | 97 | Enter the libsoc.git directory 98 | 99 | cd libsoc.git 100 | 101 | Run `autoreconf` to generate the libsoc configure scripts 102 | 103 | autoreconf -i 104 | 105 | Configure the libsoc library with the required features 106 | 107 | ```text 108 | ./configure 109 | 110 | [--disable-debug] 111 | [--enable-python=] 112 | [--enable-board=] 113 | [--with-board-configs] 114 | ``` 115 | 116 | ```text 117 | --disable-debug 118 | 119 | disables the debug code, turn off the debug to 120 | get the fastest operation but at the cost of any 121 | debug print outs. Omitting this flag will leave 122 | debug enabled. 123 | ``` 124 | 125 | ```text 126 | --enable-python= 127 | 128 | enable Python language bindings to libsoc API. 129 | Value can be empty for autodetect, the value 2 130 | or 3 to search the PATH environment variable 131 | for python2 or python3, or an absolute path to 132 | a python binary. 133 | ``` 134 | 135 | ```text 136 | --enable-board= 137 | 138 | install a specific board config file to 139 | $(sysdir)/libsoc.conf. This enables the use of 140 | the board pin name lookup functions and 141 | automatic board config probing. Supported boards 142 | can be found under ./contrib/board_files. If 143 | --with-board-configs is also used, a symlink 144 | will be created instead of copying a single file. 145 | ``` 146 | 147 | ```text 148 | --with-board-configs 149 | 150 | install all the contributed board configuration 151 | files to $PREFIX/share/libsoc. 152 | ``` 153 | 154 | Compile the code using make 155 | 156 | ```text 157 | make 158 | ``` 159 | 160 | Install the library using make 161 | 162 | ```text 163 | make install 164 | ``` 165 | 166 | ## Documentation 167 | 168 | Written documentation can be found at 169 | [http://jackmitch.github.io/libsoc](http://jackmitch.github.io/libsoc). 170 | 171 | Test cases can be found in the 172 | [test/](https://github.com/jackmitch/libsoc/tree/master/test) directory 173 | from the root of the project. 174 | 175 | All functions and types are also documented directly in the code in the 176 | application header files under 177 | [lib/include](https://github.com/jackmitch/libsoc/tree/master/lib/include). 178 | 179 | ## Licencing 180 | 181 | libsoc is licenced under the LGPLv2.1, please see the COPYING file for 182 | further details. 183 | 184 | ## Contributing 185 | 186 | libsoc is open-source software and as such you are welcome to browse the 187 | code and either add features, or fix bugs. Please submit pull requests, 188 | and bugs to [libsoc@github](http://www.github.com/jackmitch/libsoc). 189 | If you have any comments or questions, I can be contacted by email at the 190 | address [jack@embed.me.uk](mailto:jack@embed.me.uk). 191 | -------------------------------------------------------------------------------- /static-docs/docs/python.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jackmitch/libsoc/545b354968a9d03008e1e86e14c58e3f8423a20c/static-docs/docs/python.md -------------------------------------------------------------------------------- /static-docs/mkdocs.yml: -------------------------------------------------------------------------------- 1 | site_name: libsoc 2 | repo_url: http://github.com/jackmitch/libsoc 3 | site_description: libsoc library documentation 4 | 5 | theme: cinder 6 | 7 | pages: 8 | - Introduction: index.md 9 | - C API: 10 | - GPIO: c/gpio.md 11 | - SPI (WIP): c/spi.md 12 | - I2C: c/i2c.md 13 | - PWM: c/pwm.md 14 | - DEBUG (WIP): c/debug.md 15 | - Python Bindings (WIP): python.md 16 | -------------------------------------------------------------------------------- /test/board_test.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "libsoc_board.h" 6 | 7 | #define _write(fd, buf) write(fd, buf, sizeof(buf)-1) 8 | 9 | int main(void) 10 | { 11 | int fails = 0; 12 | char template[] = "/tmp/fileXXXXXX"; 13 | int fd = mkstemp(template); 14 | board_config *config; 15 | unsigned int id; 16 | 17 | _write(fd, "[GPIO]\n"); 18 | _write(fd, "GPIO_FOO= 123\n"); 19 | _write(fd, "\n"); 20 | _write(fd, "GPIO_BAR =42 \n"); 21 | _write(fd, "GPIO_B = 421 \n"); 22 | _write(fd, "GPIO_C =21 \n"); 23 | close(fd); 24 | 25 | setenv("LIBSOC_GPIO_CONF", template, 1); 26 | config = libsoc_board_init(); 27 | 28 | 29 | id = libsoc_board_gpio_id(config, "GPIO_BAR"); 30 | if (id != 42) 31 | { 32 | printf("ERROR: GPIO_BAR %d != 42\n", id); 33 | fails++; 34 | } 35 | id = libsoc_board_gpio_id(config, "GPIO_FOO"); 36 | if (id != 123) 37 | { 38 | printf("ERROR: GPIO_FOO %d != 123\n", id); 39 | fails++; 40 | } 41 | id = libsoc_board_gpio_id(config, "GPIO_B"); 42 | if (id != 421) 43 | { 44 | printf("ERROR: GPIO_B %d != 421\n", id); 45 | fails++; 46 | } 47 | id = libsoc_board_gpio_id(config, "GPIO_C"); 48 | if (id != 21) 49 | { 50 | printf("ERROR: GPIO_C %d != 21\n", id); 51 | fails++; 52 | } 53 | 54 | printf("Tests completed with %d failure(s).\n", fails); 55 | libsoc_board_free(config); 56 | unlink(template); 57 | return fails; 58 | } 59 | 60 | -------------------------------------------------------------------------------- /test/gpio_test.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "libsoc_gpio.h" 7 | #include "libsoc_debug.h" 8 | 9 | /** 10 | * 11 | * This gpio_test is intended to be run on beaglebone white hardware 12 | * and uses pins P9_42(gpio7) and P9_27 (gpio115) connected together. 13 | * 14 | * The GPIO_OUTPUT and INPUT defines can be changed to support any board 15 | * all you need to do is ensure that the two pins are connected together 16 | * 17 | */ 18 | 19 | #define GPIO_OUTPUT 115 20 | #define GPIO_INPUT 7 21 | 22 | static int interrupt_count = 0; 23 | 24 | int callback_test(void* arg) 25 | { 26 | int* tmp_count = (int*) arg; 27 | 28 | *tmp_count = *tmp_count + 1; 29 | 30 | return EXIT_SUCCESS; 31 | } 32 | 33 | 34 | int main(void) 35 | { 36 | // Create both gpio pointers 37 | gpio *gpio_output, *gpio_input; 38 | 39 | // Enable debug output 40 | libsoc_set_debug(1); 41 | 42 | // Request gpios 43 | gpio_output = libsoc_gpio_request(GPIO_OUTPUT, LS_GPIO_SHARED); 44 | gpio_input = libsoc_gpio_request(GPIO_INPUT, LS_GPIO_SHARED); 45 | 46 | // Ensure both gpio were successfully requested 47 | if (gpio_output == NULL || gpio_input == NULL) 48 | { 49 | goto fail; 50 | } 51 | 52 | // Set direction to OUTPUT 53 | libsoc_gpio_set_direction(gpio_output, OUTPUT); 54 | 55 | // Check the direction 56 | if (libsoc_gpio_get_direction(gpio_output) != OUTPUT) 57 | { 58 | printf("Failed to set direction to OUTPUT\n"); 59 | goto fail; 60 | } 61 | 62 | // Set direction to INPUT 63 | libsoc_gpio_set_direction(gpio_input, INPUT); 64 | 65 | // Check the direction 66 | if (libsoc_gpio_get_direction(gpio_input) != INPUT) 67 | { 68 | printf("Failed to set direction to INPUT\n"); 69 | goto fail; 70 | } 71 | 72 | // Set level HIGH and check level in software and hardware 73 | libsoc_gpio_set_level(gpio_output, HIGH); 74 | 75 | if (libsoc_gpio_get_level(gpio_output) != HIGH) 76 | { 77 | printf("Failed setting gpio level HIGH\n"); 78 | goto fail; 79 | } 80 | 81 | if (libsoc_gpio_get_level(gpio_input) != HIGH) 82 | { 83 | printf("GPIO hardware read was not HIGH\n"); 84 | goto fail; 85 | } 86 | 87 | // Set level LOW and check level in software and hardware 88 | libsoc_gpio_set_level(gpio_output, LOW); 89 | 90 | if (libsoc_gpio_get_level(gpio_output) != LOW) 91 | { 92 | printf("Failed setting gpio level LOW\n"); 93 | goto fail; 94 | } 95 | 96 | if (libsoc_gpio_get_level(gpio_input) != LOW) 97 | { 98 | printf("GPIO hardware read was not LOW\n"); 99 | goto fail; 100 | } 101 | 102 | // Turn off debug printing for fast toggle 103 | libsoc_set_debug(0); 104 | 105 | int i; 106 | 107 | // Toggle the GPIO 1000 times as fast as it can go 108 | for (i=0; i<1000; i++) 109 | { 110 | libsoc_gpio_set_level(gpio_output, HIGH); 111 | libsoc_gpio_set_level(gpio_output, LOW); 112 | } 113 | 114 | // Turn debug back on 115 | libsoc_set_debug(1); 116 | 117 | // Set edge to RISING 118 | libsoc_gpio_set_edge(gpio_input, RISING); 119 | 120 | // Check Edge 121 | if (libsoc_gpio_get_edge(gpio_input) != RISING) 122 | { 123 | printf("Failed to set edge to RISING\n"); 124 | goto fail; 125 | } 126 | 127 | // Set edge to FALLING 128 | libsoc_gpio_set_edge(gpio_input, FALLING); 129 | 130 | // Check Edge 131 | if (libsoc_gpio_get_edge(gpio_input) != FALLING) 132 | { 133 | printf("Failed to set edge to FALLING\n"); 134 | goto fail; 135 | } 136 | 137 | // Set edge to BOTH 138 | libsoc_gpio_set_edge(gpio_input, BOTH); 139 | 140 | // Check Edge 141 | if (libsoc_gpio_get_edge(gpio_input) != BOTH) 142 | { 143 | printf("Failed to set edge to BOTH\n"); 144 | goto fail; 145 | } 146 | 147 | // Set edge to NONE 148 | libsoc_gpio_set_edge(gpio_input, NONE); 149 | 150 | // Check Edge 151 | if (libsoc_gpio_get_edge(gpio_input) != NONE) 152 | { 153 | printf("Failed to set edge to NONE\n"); 154 | goto fail; 155 | } 156 | 157 | pid_t childPID; 158 | 159 | // Fork the process so the parent process can wait for the interrupt 160 | // on GPIO_INPUT and the child process can generate the interrupt from 161 | // GPIO_OUTPUT 162 | 163 | childPID = fork(); 164 | 165 | if(childPID >= 0) 166 | { 167 | if (childPID == 0) 168 | { 169 | // Allow time to setup the interrupt 170 | sleep(1); 171 | 172 | // Create a falling interrupt 173 | libsoc_gpio_set_level(gpio_output, HIGH); 174 | libsoc_gpio_set_level(gpio_output, LOW); 175 | 176 | exit(EXIT_SUCCESS); 177 | } 178 | } 179 | else 180 | { 181 | printf("Fork failed, interrupt won't be triggered\n"); 182 | } 183 | 184 | // Set the edge to falling in order to test interrupts 185 | libsoc_gpio_set_edge(gpio_input, FALLING); 186 | 187 | // Wait 10 seconds for falling interrupt to occur on GPIO_INPUT 188 | int ret = libsoc_gpio_wait_interrupt(gpio_input, 10000); 189 | 190 | if (ret == LS_INT_TRIGGERED) 191 | { 192 | printf("Interrupt caught!\n"); 193 | } 194 | else 195 | { 196 | printf("Interrupt missed!\n"); 197 | } 198 | 199 | int status; 200 | 201 | wait(&status); 202 | 203 | 204 | // Setup callback 205 | libsoc_gpio_callback_interrupt(gpio_input, &callback_test, (void*) &interrupt_count); 206 | 207 | // Turn off debug 208 | libsoc_set_debug(0); 209 | 210 | printf("Setting off interrupt generation...\n"); 211 | 212 | // Toggle the GPIO to generate interrupts 213 | for (i=0; i<10000; i++) 214 | { 215 | libsoc_gpio_set_level(gpio_output, HIGH); 216 | libsoc_gpio_set_level(gpio_output, LOW); 217 | 218 | // Let the other thread get a look in otherwise interrupt success is 219 | // ~85%, with usleep(1) success is nearly always %100 with no other load. 220 | usleep(1); 221 | } 222 | 223 | // Turn debug back on 224 | libsoc_set_debug(1); 225 | 226 | printf("Caught %d of 10000 interrupts\n", interrupt_count); 227 | 228 | // Cancel the callback on interrupt 229 | libsoc_gpio_callback_interrupt_cancel(gpio_input); 230 | 231 | fail: 232 | 233 | // If gpio_request was successful 234 | if (gpio_input) 235 | { 236 | // Free gpio request memory 237 | libsoc_gpio_free(gpio_input); 238 | } 239 | 240 | if (gpio_output) 241 | { 242 | // Free gpio request memory 243 | libsoc_gpio_free(gpio_output); 244 | } 245 | 246 | return EXIT_SUCCESS; 247 | } 248 | -------------------------------------------------------------------------------- /test/gpio_test.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | import threading 3 | import time 4 | 5 | from libsoc import gpio 6 | 7 | 8 | def test_wait_for_interrupt(gpio_in, gpio_out): 9 | def signaller(gpio_out, event): 10 | event.wait() 11 | # wait 1/100th of a second and create a falling interrupt 12 | time.sleep(0.01) 13 | gpio_out.set_high() 14 | gpio_out.set_low() 15 | 16 | gpio_out.set_low() 17 | event = threading.Event() 18 | t = threading.Thread(target=signaller, args=(gpio_out, event)) 19 | t.start() 20 | 21 | gpio_in.set_edge(gpio.EDGE_FALLING) 22 | event.set() 23 | # wait up to one second for the interrupt 24 | gpio_in.wait_for_interrupt(1000) 25 | 26 | 27 | def test_interrupt_handler(gpio_in, gpio_out): 28 | class int_handler(object): 29 | hits = 0 30 | 31 | def cb(self): 32 | self.hits += 1 33 | 34 | gpio_out.set_low() 35 | gpio_in.set_direction(gpio.DIRECTION_INPUT, gpio.EDGE_FALLING) 36 | 37 | cb = int_handler() 38 | h = gpio_in.start_interrupt_handler(cb.cb) 39 | 40 | for x in range(100): 41 | time.sleep(0.01) 42 | gpio_out.set_high() 43 | gpio_out.set_low() 44 | time.sleep(0.1) 45 | h.stop() 46 | h.join() 47 | print('Sent 100 interrupts, received: %d' % cb.hits) 48 | 49 | 50 | def main(gpio_input_id, gpio_output_id): 51 | gpio_in = gpio.GPIO(gpio_input_id, gpio.DIRECTION_INPUT) 52 | gpio_out = gpio.GPIO(gpio_output_id, gpio.DIRECTION_OUTPUT) 53 | 54 | with gpio.request_gpios((gpio_in, gpio_out)): 55 | assert gpio.DIRECTION_INPUT == gpio_in.get_direction() 56 | assert gpio.DIRECTION_OUTPUT == gpio_out.get_direction() 57 | 58 | gpio_out.set_high() 59 | assert gpio_out.is_high() 60 | assert gpio_in.is_high() 61 | 62 | gpio_out.set_low() 63 | assert not gpio_out.is_high() 64 | assert not gpio_in.is_high() 65 | 66 | gpio.GPIO.set_debug(False) 67 | for i in range(1000): 68 | gpio_out.set_high() 69 | gpio_out.set_low() 70 | 71 | gpio.GPIO.set_debug(True) 72 | edges = (gpio.EDGE_RISING, gpio.EDGE_FALLING, 73 | gpio.EDGE_BOTH, gpio.EDGE_NONE) 74 | for edge in edges: 75 | gpio_in.set_edge(edge) 76 | assert edge == gpio_in.get_edge() 77 | 78 | test_wait_for_interrupt(gpio_in, gpio_out) 79 | test_interrupt_handler(gpio_in, gpio_out) 80 | 81 | 82 | if __name__ == '__main__': 83 | import os 84 | gpio_input_id = int(os.environ.get('GPIO_IN', '7')) 85 | gpio_output_id = int(os.environ.get('GPIO_OUT', '115')) 86 | main(gpio_input_id, gpio_output_id) 87 | -------------------------------------------------------------------------------- /test/i2c_test.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "libsoc_i2c.h" 10 | #include "libsoc_debug.h" 11 | 12 | /** 13 | * 14 | * This i2c_test is intended to be run on beaglebone white hardware 15 | * and uses the I2C2 which is device id 1 by default, as not all 3 I2C 16 | * busses are actiavted, and i2c devices are enumerated by amount. 17 | * 18 | * The i2c bus is on pins P9_19 as SCL, P9_20 as SDA 19 | * 20 | * The BeagleBone is connected to a ST MicroElectronics M24C01-WBN6P 1K 21 | * EEPROM 22 | * 23 | * The test covers writing 32 bytes of random data, to a random page 24 | * on the EEPROM. It then reads the page back, and compares the data 25 | * read against the data sent, the test passes if all data matches. 26 | * 27 | */ 28 | 29 | #define I2C_BUS 1 30 | #define ADDRESS 0b1010000 31 | 32 | #define EEPROM_SIZE 128*8 33 | #define EEPROM_PAGE_SIZE 16 34 | #define EEPROM_NUM_PAGES EEPROM_SIZE/EEPROM_PAGE_SIZE 35 | 36 | int main() 37 | { 38 | // Turn debug on 39 | libsoc_set_debug(1); 40 | 41 | // Initialise i2c struct 42 | i2c *eeprom = libsoc_i2c_init(I2C_BUS, ADDRESS); 43 | 44 | if (eeprom == NULL) { 45 | printf("Failed to get I2C device!\n"); 46 | return EXIT_FAILURE; 47 | } 48 | 49 | // Set the timeout for the i2c slave 50 | libsoc_i2c_set_timeout(eeprom, 1); 51 | 52 | // Setup the seed for the random number 53 | struct timeval t1; 54 | gettimeofday(&t1, NULL); 55 | srand(t1.tv_usec * t1.tv_sec); 56 | 57 | // Buffers for reading and writing 58 | uint8_t data[EEPROM_PAGE_SIZE+1]; 59 | uint8_t data_read[EEPROM_PAGE_SIZE]; 60 | 61 | // Get a random page number 62 | uint8_t page = (rand() % EEPROM_NUM_PAGES) * EEPROM_PAGE_SIZE; 63 | int i, ret; 64 | 65 | // The first byte of the i2c write in the EEPROM protocol is the page 66 | data[0] = page; 67 | 68 | // Fill the rest of the write buffer with random data 69 | for (i=1; i<(EEPROM_PAGE_SIZE+1); i++) { 70 | data[i] = rand() % 255; 71 | } 72 | 73 | // Write page 74 | printf ("Writing to page starting at byte address: %d\n", page); 75 | ret = libsoc_i2c_write(eeprom, data, EEPROM_PAGE_SIZE+1); 76 | 77 | printf("Waiting for data to be written\n"); 78 | 79 | // Wait for the page to be written (spin on bogus write till we get 80 | // an ACK, signalling the EEPROM has written the page) 81 | while (libsoc_i2c_write(eeprom, &page, 1) == EXIT_FAILURE) { 82 | printf("Waiting...\n"); 83 | usleep(1); 84 | } 85 | 86 | printf("Data sucessfully written!\n"); 87 | 88 | printf("Reading data\n"); 89 | 90 | // Write page address to read 91 | ret = libsoc_i2c_write(eeprom, &page, 1); 92 | 93 | // Read page 94 | ret = libsoc_i2c_read(eeprom, data_read, EEPROM_PAGE_SIZE); 95 | 96 | if (ret != EXIT_SUCCESS) { 97 | printf("Read page failed\n"); 98 | } 99 | 100 | printf ("Reading page starting at byte address: %d\n", page); 101 | 102 | // Print out read back page contects, while checking validity 103 | for (i=0; i 2 | #include 3 | #include 4 | #include 5 | 6 | #include "libsoc_pwm.h" 7 | #include "libsoc_debug.h" 8 | 9 | /** 10 | * 11 | * This pwm_test is intended to be run on beaglebone white hardware, 12 | * however, it will work on any board with a PWM sysfs implementation. 13 | * 14 | * The PWM sysfs interface was introduced in linux 3.12, if your kernel 15 | * is older than this you will need to update or backport the PWM sysfs 16 | * patch. 17 | * 18 | * PWM sysfs Documentation: https://www.kernel.org/doc/Documentation/pwm.txt 19 | * 20 | */ 21 | 22 | #define PWM_OUTPUT_CHIP 0 23 | #define PWM_CHIP_OUTPUT 1 24 | 25 | int main(void) 26 | { 27 | int ret = EXIT_SUCCESS; 28 | 29 | libsoc_set_debug(1); 30 | 31 | pwm *pwm = libsoc_pwm_request(PWM_OUTPUT_CHIP, PWM_CHIP_OUTPUT, LS_PWM_SHARED); 32 | 33 | if (!pwm) 34 | { 35 | printf("Failed to get PWM\n"); 36 | goto fail; 37 | } 38 | 39 | libsoc_pwm_set_enabled(pwm, ENABLED); 40 | 41 | int enabled = libsoc_pwm_get_enabled(pwm); 42 | 43 | if (!enabled) 44 | { 45 | printf("Failed enabling test\n"); 46 | ret = EXIT_FAILURE; 47 | goto fail; 48 | } 49 | 50 | libsoc_pwm_set_enabled(pwm, DISABLED); 51 | 52 | enabled = libsoc_pwm_get_enabled(pwm); 53 | 54 | if (enabled) 55 | { 56 | printf("Failed disabling test\n"); 57 | ret = EXIT_FAILURE; 58 | goto fail; 59 | } 60 | 61 | libsoc_pwm_set_period(pwm, 10); 62 | 63 | int current_period = libsoc_pwm_get_period(pwm); 64 | 65 | if (current_period != 10) 66 | { 67 | printf("Failed period test\n"); 68 | goto fail; 69 | } 70 | 71 | libsoc_pwm_set_duty_cycle(pwm, 5); 72 | 73 | int current_duty = libsoc_pwm_get_duty_cycle(pwm); 74 | 75 | if (current_duty != 5) 76 | { 77 | printf("Failed duty test\n"); 78 | goto fail; 79 | } 80 | 81 | // This command should fail as the duty should not 82 | // be allowed to be greater than the period 83 | libsoc_pwm_set_duty_cycle(pwm, 15); 84 | 85 | current_duty = libsoc_pwm_get_duty_cycle(pwm); 86 | 87 | if (current_duty != 5) 88 | { 89 | printf("Failed duty test, this may be a problem with the kernel driver, continuing...\n"); 90 | } 91 | else 92 | { 93 | printf("Driver correctly responded to setting duty higher than period, with error\n"); 94 | } 95 | 96 | libsoc_pwm_set_polarity(pwm, INVERSED); 97 | 98 | int polarity = libsoc_pwm_get_polarity(pwm); 99 | 100 | if (polarity != INVERSED) 101 | { 102 | printf("Failed polarity test, this may be an error, or it might not be supported by your driver\n"); 103 | } 104 | 105 | libsoc_pwm_set_polarity(pwm, NORMAL); 106 | 107 | polarity = libsoc_pwm_get_polarity(pwm); 108 | 109 | if (polarity != NORMAL) 110 | { 111 | printf("Failed polarity test, this may be an error, or it might not be supported by your driver\n"); 112 | } 113 | 114 | fail: 115 | 116 | libsoc_pwm_free(pwm); 117 | 118 | return ret; 119 | } 120 | -------------------------------------------------------------------------------- /test/spi_test.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "libsoc_spi.h" 10 | #include "libsoc_debug.h" 11 | 12 | /** 13 | * 14 | * This spi_test is intended to be run on beaglebone white hardware 15 | * and uses the SPIDEV1 device on pins P9_31 as SCLK, P9_29 as SI, 16 | * P9_30 as as SO, P9_28 as CS. 17 | * 18 | * The BeagleBone is connected to a MicroChip 25LC640-I/P 64K EEPROM. 19 | * 20 | * The test covers writing 32 bytes of random data, to a random page 21 | * on the EEPROM. It then reads the page back, and compares the data 22 | * read against the data sent, the test passes if all data matches. 23 | * 24 | */ 25 | 26 | #define SPI_DEVICE 1 27 | #define CHIP_SELECT 0 28 | 29 | #define EEPROM_SIZE 8192*8 30 | #define EEPROM_NUM_PAGES EEPROM_SIZE/32 31 | 32 | #define WREN 0x06 33 | #define WRDI 0x04 34 | #define WRITE 0x02 35 | #define READ 0x03 36 | #define RDSR 0x05 37 | 38 | static uint8_t tx[35], rx[35]; 39 | 40 | uint8_t read_status_register(spi* spi_dev) { 41 | 42 | printf("Reading STATUS register\n"); 43 | 44 | tx[0] = RDSR; 45 | tx[1] = 0; 46 | rx[0] = 0; 47 | rx[1] = 0; 48 | 49 | libsoc_spi_rw(spi_dev, tx, rx, 2); 50 | 51 | printf("STATUS is 0x%02x\n", rx[1]); 52 | 53 | return rx[1]; 54 | } 55 | 56 | int write_page(spi* spi_dev, uint16_t page_address, uint8_t* data, int len) { 57 | 58 | printf("Writing to page %d\n", page_address); 59 | 60 | page_address = page_address * 32; 61 | 62 | tx[0] = WRITE; 63 | 64 | tx[1] = (page_address >> 8); 65 | tx[2] = page_address; 66 | 67 | if (len > 32) { 68 | printf("Page size is 32 bytes\n"); 69 | return EXIT_FAILURE; 70 | } 71 | 72 | int i; 73 | 74 | for (i=0; i> 8); 108 | tx[2] = page_address; 109 | 110 | libsoc_spi_rw(spi_dev, tx, rx, (len+3)); 111 | 112 | int i; 113 | 114 | for (i=0; i 0 ]] 7 | do 8 | 9 | key="$1" 10 | 11 | case $key in 12 | --no-python2) 13 | python2=0 14 | ;; 15 | --no-python3) 16 | python3=0 17 | ;; 18 | *) 19 | echo "unrecognised argument" 20 | exit 1 21 | ;; 22 | esac 23 | 24 | shift 25 | done 26 | 27 | cd .. 28 | 29 | autoreconf -i 30 | ./configure ${CONFIGURE_FLAGS} 31 | make 32 | make clean 33 | 34 | ./configure ${CONFIGURE_FLAGS} --prefix=$(pwd)/test/tmpinstall 35 | make 36 | make install 37 | find test/ -name *python* | grep -qz . && { echo "python found when not configured"; exit 1; rm -r test/tmpinstall; } 38 | rm -r test/tmpinstall 39 | make clean 40 | 41 | ./configure ${CONFIGURE_FLAGS} --enable-python=no --prefix=$(pwd)/test/tmpinstall 42 | make 43 | make install 44 | find test/ -name *python* | grep -qz . && { echo "python found when set to no"; exit 1; rm -r test/tmpinstall; } 45 | rm -r test/tmpinstall 46 | make clean 47 | 48 | if ./configure ${CONFIGURE_FLAGS} --enable-python=/usr/bin/python-nope ; then 49 | echo "configure succeeded when given bad python path" 50 | exit 1 51 | fi 52 | 53 | if [ $python2 -ne 0 ]; then 54 | 55 | ./configure ${CONFIGURE_FLAGS} --enable-python --prefix=$(pwd)/test/tmpinstall 56 | make 57 | make install 58 | find test/ -name *python* | grep -qz . || { echo "python auto failed"; exit 1; rm -r test/tmpinstall; } 59 | rm -r test/tmpinstall 60 | make clean 61 | 62 | ./configure ${CONFIGURE_FLAGS} --enable-python=2 --prefix=$(pwd)/test/tmpinstall 63 | make 64 | make install 65 | find test/ -name *python2* | grep -qz . || { echo "python2 version build failed"; exit 1; rm -r test/tmpinstall; } 66 | rm -r test/tmpinstall 67 | make clean 68 | 69 | ./configure ${CONFIGURE_FLAGS} --enable-python=/usr/bin/python2 --prefix=$(pwd)/test/tmpinstall 70 | make 71 | make install 72 | find test/ -name *python2* | grep -qz . || { echo "python2 full path build failed"; exit 1; rm -r test/tmpinstall; } 73 | rm -r test/tmpinstall 74 | make clean 75 | 76 | fi 77 | 78 | if [ $python3 -ne 0 ]; then 79 | 80 | ./configure ${CONFIGURE_FLAGS} --enable-python --prefix=$(pwd)/test/tmpinstall 81 | make 82 | make install 83 | find test/ -name *python* | grep -qz . || { echo "python auto build failed"; exit 1; rm -r test/tmpinstall; } 84 | rm -r test/tmpinstall 85 | make clean 86 | 87 | ./configure ${CONFIGURE_FLAGS} --enable-python=3 --prefix=$(pwd)/test/tmpinstall 88 | make 89 | make install 90 | find test/ -name *python3* | grep -qz . || { echo "python3 version only build failed"; exit 1; rm -r test/; } 91 | rm -r test/tmpinstall 92 | make clean 93 | 94 | ./configure ${CONFIGURE_FLAGS} --enable-python=/usr/bin/python3 --prefix=$(pwd)/test/tmpinstall 95 | make 96 | make install 97 | find test/ -name *python3* | grep -qz . || { echo "python3 full path build failed"; exit 1; rm -r test/; } 98 | rm -r test/tmpinstall 99 | make clean 100 | 101 | fi 102 | 103 | ./configure ${CONFIGURE_FLAGS} --enable-board=beaglebone_black 104 | make 105 | make clean 106 | 107 | ./configure ${CONFIGURE_FLAGS} --with-board-configs 108 | make 109 | make clean 110 | 111 | ./configure ${CONFIGURE_FLAGS} --disable-debug 112 | make 113 | make clean 114 | 115 | echo -e "\n\n\n\n.................. SUCCESS ...................\n\n\n\n" 116 | --------------------------------------------------------------------------------