1libmraa Internals {#internals} 2================= 3 4For building see @ref building. This will describe the general internal build 5of libmraa and will be useful to developers who'd like to understand more of 6how libmraa works or who'd like to add additional platforms. The internals will 7deal with the C API as that is the low level API which libmraa is built around. 8Note that C++ is simply a header only wrapper of the C API. 9 10libmraa has the philosophy that the board mapping is what we typically use in 11the API with the execption of i2c/spi bus numbering as they are typically not 12labelled on boards and so we use the kernel numbering scheme. Whilst this can 13confuse some, it's typically not an issue as platforms rarely expose more than 14one of these for user use and so when this is the case, libmraa will always use 15the bus in the pinmapper. For example edison uses i2c #6 but since there is 16only one, libmraa will try to be helpful and everything is treated as 6 when 17doing a mraa_i2c_init(). The _raw functions will override the pinmapper and can 18be accessed without a valid board configuration. This can be helpful either in 19development of platform configurations for mraa or when modifying kernels 20etc... Internally the mechanism is used heavily. 21 22In libmraa, all code is split into 7 modules, src/{i2c, spi, gpio, uart, pwm, 23aio and common}. These should be fairly self explanatory in goals/purpose but a 24few work in different ways. Public APIs are stored in api/ and internal headers 25are in include/ 26 27### Logging ### 28 29Logging is now done purely in syslog(). Note that on platforms running systemd 30journald will intercept syslog(3) calls and log to the journal instead. You can 31set the log mask by using mraa_set_log_level(). Doing a DEBUG build of libmraa 32will also cause the DEBUG macro to be defined which will cause the syslog mask 33to be unset. 34 35### Contexts ### 36 37libmraa uses contexts to store all information, this context cannot be accessed 38by the user and so it's layout can and may be changed without warning to users. 39If an init() function fails it will return NULL and further calls with this 40context will lead to undefined behaviour. 41 42### Pinmapper ### 43 44The mraa_board_t is defined in mraa/common.h. It's a mostly static structure 45initialised during mraa_init(). The pinmap file in 46src/{arch}/{manufacturer}_{boardname}_{revision}.c then fills this array. It's 47also where platform hooks can be defined, functions that will be run at various 48'hook' points in the code. 49 50The mraa_pininfo_t structure needs to be set for the board pincount (set in a 51macro in the platform configuration header. Every pin will have a 52mraa_pincapabilities_t which will define what it can do. The doxygen 53documentation explains how this works but it's essentially a bitfield which 54needs to be set for every capability the pin can have. Gpios can have multiple 55muxes which will be set at the gpio init before it can be toggled. 56 57### i2c ### 58 59I2c from userspace in GNU/Linux is handled by character devices handled by the 60kernel driver i2c-dev. For more details the i2c/dev-interface documentation 61file in the kernel is the place to go. 62 63In libmraa, we re-use part of a library - libi2c from RoadNarrows - 64i2c/smbus.c. This library simply makes it easier for us to handle the error 65conditions that can arrise when writing on i2c buses. Essentially the API is 66fairly simple consisting of writes & reads. 67 68Careful - on alot of platforms i2cdetect will often crash. To findi your i2c 69addresses please look at your sensor's datasheet! If using i2cdetect most 70platforms do not support SMBus quick write so use the '-r' flag. 71 72### spi ### 73 74Mraa deals exclusively with spidev, so when we say bus we really mean bus + 75chip select from spidev. Spi(0) could lead to spidev5.1 and Spi(1) to 76spidev5.2. Typically on a micro using a random gpio as a chip select works 77well, and on some platforms if one is careful with threads this can work well 78with mraa. However when a kernel module shares the same bus as spidev (but on a 79different CS) this behaviour is *very* dangerous. Platforms such as Galileo 80Gen2 & Edison + Arduino breakout board work this way. Mraa will not help you in 81using a non hardware chip select, do so at your own peril! 82 83### gpio ### 84 85GPIO is probably the most complicated and odd module in libmraa. It is based on 86the gpiolib kernel driver framework which uses sysfs. There is a lot of good 87documentation in gpio/sysfs.txt in the kernel docs. 88 89The main issue is that gpios on hobbyist boards typically come with a number of 90muxers or level shifters and are often mapped in crazy ways. libmraa's goal is 91to make the label on your board match the API :) We hope that pleases you. 92 93Because boards are very different we use alot of platform hooks (@ref hooks) to 94make the initialisation work on all platforms. The hope is that simple 95platforms with no level shifters or expanders will work with just the pinmap 96definition. 97 98GPIOs are typically interfaced via sysfs because that's easier for us but we 99can also work with fast gpio. This is typically preffered to do mmap gpio 100access. This is however trickier and typically relies on lots of platform 101hooks. By default we support hitting /dev/mem or another device at specific 102addresses to toggle gpios which is how mmap access works on some boards. 103 104Note that in Linux gpios are numbered from ARCH_NR_GPIOS down. This means that 105if ARCH_NR_GPIOS is changed, the gpio numbering will change. In 3.18+ the 106default changed from 256 to 512, sadly the value cannot be viewed from 107userspace so we rely on the kernel version to extrapolate the likely value. 108 109### uart ### 110 111libmraa does not support UART/serial as there are many good libraries that do 112this already. In the future we may wrap or use one. However the class exists to 113set the pinmapper correctly for uart to work on some platforms. 114 115### pwm ### 116 117Internally everything with PWM in mraa is in microseconds because that's what 118the linux kernel uses and is probably all the granularity we'll ever 119need/achieve with the kind of hardware we're targetting. Board configuration 120pwm max/min values are always set in microseconds. 121 122### aio ### 123 124AIO pins are numbered after GPIO pins. This means that on Arduino style boards 125pin 14 is A0. Typically mraa will only support an ADC if a platform ships with 126one and has a good kernel module for it. Extra i2c/spi ADCs can be supported 127via something like UPM but are unlikely to receive support in mraa at the moment. 128 129Note that giving mraa_aio_init(0) will literally query the pinmapper for 130board->gpio_count + 0 so you must place your aio pins after gpio_count. This is 131the default behaviour but can of course be overriden by advance function 132pointers. Whilst maybe not the sanest of defaults, most of the hobbyist boards 133we deal with follow a naming pattern similar to Arduino or have no ADC so for 134now we have considered this sensible. 135 136### Initialisation ### 137 138mraa_init() needs to be called in order to initialise the platform files or 139'pinmap'. Because calling this is tedious libmraa uses a C constructor to run 140mraa_init on library load. This means that it is not possible to stop this 141running and all function calls like mraa_set_log_level() will not work during 142mraa_init(). This feature is supported by most sane compilers and libcs but you 143can turn off CTORS in uclibc, though I've yet to find a configuration with 144someone doing that. mraa_init() can be called multiple times if you feel like 145being 'safe'. 146 147In the SWIG modules mraa_init() is called during the %init stage of the module 148loading. This is simply to avoid mraa_init() running 'too' early, though I've 149never seen an issue in running it in a CTOR. 150 151### SWIG ### 152 153At the time when libmraa was created (still the case?) the only - working - 154API/wrapper generation tool that supported nodejs was SWIG. For more general 155information on SWIG please see the SWIG documentation. 156 157The src/{javascript, python} & src/mraa.i folders contain all the files for the 158SWIG generation. The C++ headers in api/mraa/ are given as input sources to 159SWIG. SWIG modules do not link to libmraa (although maybe that would be a good 160idea...) 161 162Typemaps are used heavily to map uint8_t* pointers to bytearrays and 163node_buffers. These are native python & node.js types that represent uint8_t 164data the best and are very well supported in both languages. Argument 165conversions and memory allocations are performed so the performance of using 166these functions compared to the C/C++ equivalent will likely be a little lower, 167however it is much more natural than using carrays.i typemap library. 168 169### NPM ### 170 171mraa is published on NPM, there is a target to prebuild a mraa src tarball that 172can be built with node-gyp. The way this works is to use the mraa_LIB_SRCS 173array to generate a binding.gyp file from the skeleton binding.gyp.cmake in 174src/javascript. Because we don't expect most NPM users to have SWIG we 175precompile the src/mraajsJAVASCRIPT_wrap.cxx. The src/version.c is already 176known since this is a static tarball so we write that too. These files are 177placed not in a build/ directory but in the main mraa directory. You can then 178tar the directory up and send it to NPM. This is done automatically on every 179commit by our automated build system. 180 181