Difference between revisions of "AsDevices"

From ArmadeusWiki
Jump to: navigation, search
(Development planning)
(Development planning)
 
(98 intermediate revisions by 7 users not shown)
Line 1: Line 1:
{{Under_Construction}}
 
  
AsDevices is an ARMadeus specific library that simplify APF-board devices usages for developer. This library is written to be used with C, C++ and Python languages.
+
AsDevices is an Armadeus specific library that simplify APF/OPOS boards devices usage for developers. This library is written to be used with C, C++, Python languages.
 +
The core is written in C and other languages support is done with "wrappers". This library can also emulate some wiringPi functionalities (in recent versions).
 +
 
 +
{{Note| This library is under development, see the [[AsDevices#Development_planning | Development planning]] to know which functionality is completed.}}
  
 
== Install AsDevices on target ==
 
== Install AsDevices on target ==
 
+
===Buildroot===
The library is included in Buildroot menu, to use it just select it in «make
+
The library is included in Buildroot menu, to use it just select it (if not already installed on your target, like on [[OPOS6UL]]):
menuconfig» :
+
<pre class="host">
 +
$ make menuconfig
 +
</pre>
  
 
<pre class="config">
 
<pre class="config">
Package Selection for the target --->
+
...
     *** Armadeus specific packages *** 
+
Target packages --->
    [*] as_devices  
+
     ...
    [*]  wrapper C++
+
    Armadeus specific tools/utilities  --->
    [*]  wrapper Python
+
        ...
 +
        [*] as_devices
 
</pre>
 
</pre>
  
The base library is in C, to use it with C++ or Python, select the wrapper you
+
The base library is in C, to use it with C++ or Python, select the wrapper you need. (For Python you will need to select Python interpreter before as_devices wrapper).
want.
+
* Rebuild all:
 +
<pre class="host">
 +
$ make
 +
</pre>
 +
* Then reflash your rootfs
  
== Use library in an application ==
+
===Debian===
 +
<pre class="apf">
 +
root@opos6ul:~# cd
 +
root@opos6ul:~# wget --no-check-certificate https://sourceforge.net/projects/armadeus/files/as_devices/as_devices-0.18.tar.gz/download -O as_devices-0.18.tar.gz
 +
root@opos6ul:~# tar zxvf as_devices-0.18.tar.gz
 +
root@opos6ul:~# cd as_devices-0.18
 +
root@opos6ul:~/as_devices-0.18# make CC=gcc CXX=g++ c_target cpp_target
 +
                                ... now understanding why cross-compilers are great ? ;-)
  
=== In C ===
+
root@opos6ul:~/as_devices-0.18# make INSTALL_DIR=/ install
 +
</pre>
  
To use AsDevices library in a C program, include the header of the device needed (all C headers are under ''${ARMADEUS_PATH}/target/package/as_devices/c/'' directory ). For example with apf27_pwm :
+
== Generate doxygen documentation ==
 +
* If ''doxygen'' isn't installed on your Linux distribution, you have to install the correct package (here on *Ubuntu):
 +
<pre class="host">
 +
$ sudo apt-get install doxygen
 +
</pre>
 +
 
 +
* Then go in AsDevices root directory:
 +
<pre class="host">
 +
$ cd target/packages/as_devices
 +
</pre>
 +
* Generate the documentation with Doxygen:
 +
<pre class="host">
 +
$ doxygen Doxyfile
 +
</pre>
 +
* Documentation has been generated in ''documentation''.
 +
** Open documentation with:
 +
<pre class="host">
 +
$ firefox documentation/index.html
 +
</pre>
 +
 
 +
== Using library in C ==
 +
 
 +
All functions in AsDevices library are constructed on the same way. An as_*_open() function return a device structure or an int that represent the device used. All function take this device structure in first parameter, and a function as_*_close() close the device :
  
 
<source lang="C">
 
<source lang="C">
#include "as_apf27_pwm.h"
+
struct as_devicename_dev * as_devicename_open(<some parameters>);
 +
 
 +
as_devicename_do-something-with-device(struct as_devicename_dev *aDev, <some parameters>);
 +
 
 +
int as_devicename_close(struct as_devicename_dev *aDev);
 
</source>
 
</source>
  
And compile with following command :
+
For each library, full documentation can be found in C header in directory ''target/packages/as_devices/c''.
<source lang="bash">
+
 
arm-linux-gcc prog.c ${ARMADEUS_PATH}/buildroot/build_arm5vt/as_devices-1.0/c/libas_devices.so -o prog -I${ARMADEUS_PATH}/buildroot/build_arm5vt/as_devices-1.0/c/
+
=== I²C ===
 +
 
 +
as_i2c_* functions are used to access devices on i²c bus that doesn't have/need a Linux driver. If you want to access an i²c device, please find out if a driver is not already existing before using this method.
 +
 
 +
To open the bus, you have to know its number. On [[APF9328]] and [[APF27]] only two busses are present: number 0 and number 1. The ''open()'' function returns an int (file descriptor of the opened ''/dec/i2c-x''), that have to be passed to all other as_i2c_* functions :
 +
 
 +
<source lang="C">
 +
int as_i2c_open(unsigned int i2c_id);
 
</source>
 
</source>
  
An example of code can be found in ''${ARMADEUS_PATH}/target/package/as_devices/'' directory, take a look of ''test_c.h'' and ''main.c''.
+
Then depending on the complexity of the I2C device communication protocol, you can either use read()/write() (simple frames) or ioctl() with complex "read then write"/"write then read" messages.
  
=== In C++ ===
+
* Example (simple write()):
  
To use AsDevices library in a C++ program, include the header of the class needed (all C++ headers are under ''${ARMADEUS_PATH}/target/package/as_devices/cpp/'' directory). For example with apf27 pwm :
+
<source lang="C">
 +
#include <stdlib.h>
 +
#include <stdio.h>
  
<source lang="cpp">
+
#include <as_devices/as_i2c.h>
  
#include "as_apf27_pwm.hpp"
+
 
 +
int my_device = 0;
 +
#define MY_DEV_ADDR 0x23
 +
#define MY_I2C_BUS 1
 +
unsigned char buf[10];
 +
int ret;
 +
 
 +
...
 +
 
 +
my_device = as_i2c_open(MY_I2C_BUS);
 +
if (my_device < 0) {
 +
    printf("Can't init I2C port %d!!\n", MY_I2C_BUS);
 +
    return -1;
 +
}
 +
as_i2c_set_slave(my_device, MY_DEV_ADDR);
 +
 
 +
...
 +
 
 +
buf[0] = (unsigned char) my_val;
 +
ret = write(my_device, buf, 1);
 +
if (ret < 0)
 +
    printf("Error while sending data to device !!\n");
 +
 
 +
...
 
</source>
 
</source>
  
And compile with following command :
+
=== SPI ===
<source lang="bash">
+
 
${CXX} ${CFLAGS} prog.cpp ${C_LIB} ${CPP_LIB} -I${C_INCLUDE} -I${CPP_INCLUDE} -o prog
+
==== Usage ====
 +
To use as_spi_* function, the ''spidev'' kernel module/interface is required. See [[SPI]]
 +
page to know how to configure it.
 +
 
 +
Once the device file ''/dev/spidevx.x'' is available from the kernel, as_spi library can be used by including the ''as_spi.h'' header in your C source code:
 +
 
 +
<source lang="C">
 +
#include <as_devices/as_spi.h>
 
</source>
 
</source>
  
An example of code canbe found in ''${ARMADEUS_PATH}/target/package/as_devices/'' directory, take a look at ''test_cpp.h'' and ''main.c''.
+
Full description of the API can be found in this header (target/packages/as_devices/c/as_spi.h), available on
 +
[http://sourceforge.net/p/armadeus/code sourceforge repository].
  
=== In Python ===
+
==== Example ====
  
To use AsDevices library with python, select the Python wrapper in menuconfig then, on platform, import the module :
+
The three mains useful functions used to communicate with a slave SPI device
 +
are :
  
<source lang="Python">
+
<source lang="C">
>>> import AsDevices
+
int as_spi_open(const unsigned char *aSpidev_name);
 
</source>
 
</source>
  
All python classes available in the module can be found with the ''dir()'' function :
+
To open the ''/dev/spidevx.x'' special spi file. This function return a file
 +
handler that will be used for all othes as_spi_* function.
  
<source lang="Python">
+
<source lang="C">
>>> dir(AsDevices)
+
void as_spi_close(int aFd);
['Apf27Pwm', 'Apf27PwmError', 'NUMBER_OF_PWM', '__author__', '__builtins__', '__doc__', '__file__', '__name__', '__path__', '__versionTime__', '__version__', 'wrappers']
+
 
</source>
 
</source>
  
=== In LUA ===
+
As its name said, to close the device.
  
TODO
+
<source lang="C">
 +
uint32_t as_spi_msg(int aFd,
 +
                    uint32_t aMsg,
 +
                    size_t aLen,
 +
                    uint32_t aSpeed);
 +
</source>
  
== Devices supported by library ==
+
This function forge spi messages on MOSI pin and return MISO message.
  
 +
=== GPIO ===
 +
 +
==== Usage ====
 +
 +
To use as_gpio_* functions, the ''gpio'' kernel module is required. See [[GPIO_Driver]] page to know how to configure it.
 +
 +
Once the device files ''/dev/gpio/*'' are available , as_gpio library can be use by including ''as_gpio.h'' header in the C source code of your application.
 +
 +
<source lang="C">
 +
#include <as_devices/as_gpio.h>
 +
</source>
 +
 +
==== Example ====
 +
 +
Two examples are given, one for lightening led D14 and one to use blocking read on switch S1. This two example are made for [[APF27Dev]] daughter card.
 +
 +
* '''Lightening led'''
 +
With as_gpio, each pin port can be openned separately. The as_gpio_open() function returns a pointer on gpio pin structure declared like this:
 +
 +
<source lang="C">
 +
int ret; /* for returning value */
 +
struct as_gpio_device *pf14;
 +
</source>
 +
 +
On APF27Dev, D14 is plugged on port F pin 14, then to open it :
 +
 +
<source lang="C">
 +
pf14 = as_gpio_open('F', 14);
 +
</source>
 +
 +
GPIO must be configured in ouput mode :
 +
 +
<source lang="C">
 +
ret = as_gpio_set_pin_direction(pf14, "out");
 +
</source>
 +
 +
Then to switch LED value, just use ''as_gpio_set_pin_value()'' function:
 +
 +
<source lang="C">
 +
ret = as_gpio_set_pin_value(pf14, 1); /* led off */
 +
...
 +
ret = as_gpio_set_pin_value(pf14, 0); /* led on */
 +
</source>
 +
 +
Note that because off led wiring, led polarity is inverted (to light on set 0).
 +
 +
Once gpio pin usage is terminated, it must be closed :
 +
 +
<source lang="C">
 +
as_gpio_close(pf14);
 +
</source>
 +
 +
* '''Pressing button'''
 +
 +
The button S1 can be used to test interrupt capability of gpio. The button is plugged on gpio port F pin 13.
 +
After declaring the ''as_gpio_device'' structure, the pin port can be opened :
 +
 +
<source lang="C">
 +
struct as_gpio_device *pf13;
 +
[...]
 +
 +
pf13 = as_gpio_open('F', 13);
 +
</source>
 +
 +
To stuff must be configured before using it as interruption source, direction and IRQ mode.
 +
 +
'''direction'''
 +
<source lang="C">
 +
ret = as_gpio_set_pin_direction(pf13, "in"); /* set switch as input */
 +
</source>
 +
 +
'''IRQ mode'''
 +
There is four IRQ mode :
 +
* '''GPIO_IRQ_MODE_NOINT  ''': No interrupt, the processor will ignore event on this gpio.
 +
* '''GPIO_IRQ_MODE_RISING ''': rising edge, the processor will generate an interruption on rising edge of gpio pin.
 +
* '''GPIO_IRQ_MODE_FALLING''': falling edge, the processor will generate an interruption on falling edge of gpio pin.
 +
* '''GPIO_IRQ_MODE_BOTH  ''': both, the processor will generate an interruption on both rising or falling edge of gpio.
 +
 +
<source lang="C">
 +
ret = as_gpio_set_irq_mode(pf13, GPIO_IRQ_MODE_FALLING); /* interrupt will be generated on pushed button */
 +
</source>
 +
 +
To capture interruption, the blocking read function can be used with a timeout. If no interruption is raised after the timeout time, read function end with error value -10.
 +
 +
<source lang="C">
 +
ret = as_gpio_blocking_get_pin_value(pf13, 3, 0); /* wait for interruption for 3 seconds and 0 µs) */
 +
if(ret == -10)
 +
    printf("Timeout\n");
 +
</source>
 +
 +
=== ADC ===
 +
==== MAX1027 ====
 +
==== AS1531 ====
 +
=== DAC ===
 +
==== MAX5821 ====
 +
==== MCP4912 ====
 +
=== 93LCXX ===
 
=== PWM ===
 
=== PWM ===
 +
==== Usage ====
 +
 +
To use as_pwm_* functions, the kernel module ''imx_pwm'' needs to be loaded. See [[PWM]] page to know how to configure it.
 +
 +
Once the special files ''/sys/class/pwm/pwmX/*'' are available , as_pwm_* functions can be use by including ''as_pwm.h'' header in the C source code of your application.
 +
 +
<source lang="C">
 +
#include <as_devices/as_pwm.h>
 +
</source>
 +
 +
==== Example ====
 +
 +
<source lang="C">
 +
#include <as_devices/as_pwm.h>
 +
...
 +
 +
int main(int argc, char *argv[])
 +
{
 +
    struct as_pwm_device *my_pwm;
 +
...
 +
    my_pwm = as_pwm_open(0);
 +
    if (!my_pwm)
 +
        printf("Can't init PWM !!\n");
 +
    as_pwm_set_frequency(my_pwm, 150);
 +
    as_pwm_set_duty(my_pwm, 500);
 +
...
 +
    as_pwm_set_state(my_pwm, 1);
 +
}
 +
</source>
 +
 +
=== LED ===
 +
 +
== Using library in Python ==
 +
 +
To use AsDevices in Python, select the python wrapper in menuconfig as follow :
 +
 +
<pre class="config">
 +
Package Selection for the target  --->
 +
  *** Armadeus specific packages ***
 +
  Armadeus specific tools/utilities  ---> 
 +
    [*] as_devices
 +
    [*]  wrapper Python
 +
</pre>
 +
 +
And keep all .py file on target :
 +
<pre class="config">
 +
Package Selection for the target  --->
 +
    Interpreter languages and scripting  --->
 +
        python module format to install (.py sources and .pyc compiled)  --->
 +
            (X) .py sources and .pyc compiled
 +
</pre>
 +
then compile bsp and flash it on your board.
 +
 +
Once done, just import the module AsDevices to use all function available in library:
 +
 +
<source lang="python">
 +
import AsDevices
 +
from AsDevices import AsGpio
 +
 +
gpio = AsGpio(3)
 +
gpio.setPinDirection('out')
 +
gpio.setPinValue(1)
 +
...
 +
</source>
 +
 +
== Using library in C++ ==
 +
===SPI===
 +
* Open the spidev device given in parameters and send one byte message:
 +
<source lang="CPP">
 +
#include <iostream>
 +
 +
#include <as_devices/cpp/as_spi.hpp>
 +
 +
//#define APF_SPI      "spidev1.2" on APF27
 +
#define APF_SPI "spidev1.1" // on APF9328
 +
#define CLOCK_SPEED    1200000
 +
 +
using namespace std;
 +
 +
int main(int argc, char **argv)
 +
{
 +
        const unsigned char* spidev_name = (const unsigned char*) APF_SPI;
 +
 +
        if (argc > 1) {
 +
                spidev_name = (const unsigned char*) argv[1];
 +
        }
 +
        cout << "Opening " << spidev_name << endl;
 +
        AsSpi* o=new AsSpi(spidev_name);
 +
 +
        int speed = o->getSpeed();
 +
        cout << "Max speed =" << speed << endl;
 +
 +
        int mode = o->getMode();
 +
        cout << "Mode = " << mode << endl;
 +
 +
        char data = 'c';
 +
        unsigned long long result = o->msg((unsigned long long) data, sizeof(data), CLOCK_SPEED);
 +
        cout << "result=" << result << endl;
 +
 +
        return 0;
 +
}
 +
</source>
 +
* Makefile:
 +
<source lang="bash">
 +
CFLAGS = -I/home/xxx/buildroot/output/staging/usr/include/as_devices
 +
CFLAGS += -I/home/xxx/buildroot/output/staging/usr/include/as_devices/cpp
 +
 +
LDFLAGS = -L/home/xxx/buildroot/output/staging/usr/lib
 +
LDFLAGS += -las_devices_cpp -las_devices
 +
 +
EXEC_NAME = foo
 +
 +
all: $(EXEC_NAME)
 +
 +
$(EXEC_NAME): foo.cpp
 +
        $(CXX) $(CFLAGS) $(LDFLAGS) -Wall -o $@ $^
 +
 +
clean:
 +
        rm -rf $(EXEC_NAME)
 +
        rm -rf *.o
 +
 +
.PHONY: clean
 +
</source>
 +
 +
'''OTHER -> TODO'''
  
 
== Development planning ==
 
== Development planning ==
Line 81: Line 392:
 
{| border="1" cellpadding="5" cellspacing="0" summary="Development planning of AsDevices"
 
{| border="1" cellpadding="5" cellspacing="0" summary="Development planning of AsDevices"
 
|- style="background:#efefef;" align="center"
 
|- style="background:#efefef;" align="center"
! Name !! C functions !! C++ wrapper !! Python wrapper !! Python class !! LUA wrapper !!description  
+
! Name !! Component !! C functions !! C++ wrapper !! Python wrapper !! Python class !! description  
 
|- align="center"
 
|- align="center"
| apf27_pwm || bgcolor="orange" | To be rewritten || bgcolor="orange" | To be rewritten    || bgcolor="orange" | To be rewritten  || bgcolor="orange" | To be rewritten || bgcolor="orange" | To be rewritten  || Drive imx27 pwm
+
| [[I2C | i2c]] ||  || bgcolor="green"| Ok || bgcolor="green"| Ok ||bgcolor=#FF0000| NOK ||bgcolor=#FF0000| NOK || Drive I2C
 
|- align="center"
 
|- align="center"
| i2c || bgcolor="yellow"| Compile || bgcolor="orange"| Written but doesn't compile ||bgcolor=#FF0000| NOK ||bgcolor=#FF0000| NOK || bgcolor="yellow" | compile || Drive I2C
+
| [[SPI | spi]] || || bgcolor="green" | Ok, but not fully tested || bgcolor="green"| Ok, but not fully tested  ||bgcolor="green"| Ok, but not fully tested  || bgcolor="green"| Ok, but not fully tested || Drive SPI
 
|- align="center"
 
|- align="center"
| spi || bgcolor="green"| Compile tested || bgcolor=#FF0000| NOK  ||bgcolor=#FF0000| NOK ||bgcolor=#FF0000| NOK ||bgcolor=#FF0000| NOK || Drive SPI
+
| [[Gpio | gpio]] || || bgcolor="green"| Ok || bgcolor="green"| Ok ||bgcolor="green" | Ok ||bgcolor="green" | Ok || Drive GPIO
 
|- align="center"
 
|- align="center"
| apf27_gpio || bgcolor="yellow"| Compile || bgcolor="yellow"| Compile ||bgcolor=#FF0000| NOK ||bgcolor=#FF0000| NOK ||bgcolor=#FF0000| NOK || Drive imx27 GPIO
+
| rowspan="3" | ADC
 +
| [[ADC_max1027 | max1027]] || bgcolor="green"| Ok for SLOW mode ||bgcolor="green"| Ok ||bgcolor=#FF0000| NOK ||bgcolor=#FF0000| NOK ||  
 
|- align="center"
 
|- align="center"
| ad5258 || bgcolor=#FF0000| NOK ||bgcolor=#FF0000| NOK ||bgcolor=#FF0000| NOK ||bgcolor=#FF0000| NOK||bgcolor=#FF0000| NOK || Drive Digital potentiometer [http://www.analog.com/en/digital-to-analog-converters/digital-potentiometers/AD5258/products/product.html AD5258]
+
| [[as1531 | as1531]] || bgcolor="green"| Ok for SLOW mode ||bgcolor="green"| Ok ||bgcolor=#FF0000| NOK ||bgcolor=#FF0000| NOK ||  
 
|- align="center"
 
|- align="center"
| ds1374 || bgcolor=#FF0000| NOK ||bgcolor=#FF0000| NOK ||bgcolor=#FF0000| NOK ||bgcolor=#FF0000| NOK ||bgcolor=#FF0000| NOK || Drive RTC chip [http://www.maxim-ic.com/quick_view2.cfm/qv_pk/3806 DS1374]
+
| [[lradc | lradc]] || bgcolor="green"| Ok for SLOW mode ||bgcolor="green"| Ok ||bgcolor=#FF0000| NOK ||bgcolor=#FF0000| NOK ||  
 
|- align="center"
 
|- align="center"
| max1027 || bgcolor=#FF0000| NOK ||bgcolor=#FF0000| NOK ||bgcolor=#FF0000| NOK ||bgcolor=#FF0000| NOK ||bgcolor=#FF0000| NOK || Drive Analog to Digital chip [http://www.maxim-ic.com/quick_view2.cfm/qv_pk/3872/t/al MAX1027]
+
| rowspan="2" | DAC
 +
| [[Max5821 | max5821]] || bgcolor="green"| OK ||bgcolor="green"| Ok, but not fully tested ||bgcolor=#FF0000| NOK ||bgcolor=#FF0000| NOK ||  
 
|- align="center"
 
|- align="center"
| max5821 || bgcolor=#FF0000| NOK ||bgcolor=#FF0000| NOK ||bgcolor=#FF0000| NOK ||bgcolor=#FF0000| NOK ||bgcolor=#FF0000| NOK || Drive Digital to Analog chip [http://www.maxim-ic.com/quick_view2.cfm/qv_pk/3288/t/al MAX5821]
+
| [[Mcp4912 | mcp4912]] || bgcolor="red"| NOK ||bgcolor="green"| Ok ||bgcolor=#FF0000| NOK ||bgcolor=#FF0000| NOK ||
 +
|- align="center"
 +
| eeprom || 93LCxx ||bgcolor="green"| OK ||bgcolor="green"| OK ||bgcolor=#FF0000| NOK ||bgcolor=#FF0000| NOK ||
 +
|- align="center"
 +
| [[PWM]] || ||bgcolor="green" |  OK  ||  bgcolor="green" | OK    || bgcolor="red" | NOK  || bgcolor="red" | NOK || Drive imx27 pwm |
 +
|- align="center"
 +
| [[Backlight]] || ||bgcolor="green" |  OK  ||  bgcolor="green" | OK    || bgcolor="red" | NOK  || bgcolor="red" | NOK ||
 +
|- align="center"
 +
| [[Led | LED]] || || bgcolor="green"| Ok || bgcolor=#FF0000 | NOk ||bgcolor=#FF0000 | NOk ||bgcolor=#FF0000 | NOk || Drive LED
 +
|- align="center"
 +
| [[BMP180]] || || bgcolor="red"| NOk || bgcolor=#FF0000 | NOk || bgcolor=#FF0000 | NOk || bgcolor="green" | OK ||
 +
|- align="center"
 +
| [[HMC5883]] || || bgcolor="red"| NOk || bgcolor=#FF0000 | NOk || bgcolor=#FF0000 | NOk || bgcolor="green" | OK ||
 
|- align="center"
 
|- align="center"
| 93LCxx || bgcolor="green"| Compile tested ||bgcolor=#FF0000| NOK ||bgcolor=#FF0000| NOK ||bgcolor=#FF0000| NOK ||bgcolor=#FF0000| NOK || EEPROM memory on SPI
 
 
|}
 
|}
 +
 +
== Links ==
 +
* [https://github.com/jackmitch/libsoc libsoc] is a project similar to AsDevices.
 +
* [http://wiringpi.com/ WiringPi] is a project similar to AsDevices for RPi.On OPOS6ULDev, AsDevices provides WiringPi emulation.

Latest revision as of 17:35, 1 August 2018

AsDevices is an Armadeus specific library that simplify APF/OPOS boards devices usage for developers. This library is written to be used with C, C++, Python languages. The core is written in C and other languages support is done with "wrappers". This library can also emulate some wiringPi functionalities (in recent versions).

Note Note: This library is under development, see the Development planning to know which functionality is completed.


Install AsDevices on target

Buildroot

The library is included in Buildroot menu, to use it just select it (if not already installed on your target, like on OPOS6UL):

$ make menuconfig
...
Target packages  --->
    ...
    Armadeus specific tools/utilities  --->
        ...
        [*] as_devices

The base library is in C, to use it with C++ or Python, select the wrapper you need. (For Python you will need to select Python interpreter before as_devices wrapper).

  • Rebuild all:
$ make
  • Then reflash your rootfs

Debian

root@opos6ul:~# cd
root@opos6ul:~# wget --no-check-certificate https://sourceforge.net/projects/armadeus/files/as_devices/as_devices-0.18.tar.gz/download -O as_devices-0.18.tar.gz
root@opos6ul:~# tar zxvf as_devices-0.18.tar.gz
root@opos6ul:~# cd as_devices-0.18
root@opos6ul:~/as_devices-0.18# make CC=gcc CXX=g++ c_target cpp_target
                                ... now understanding why cross-compilers are great ? ;-)

root@opos6ul:~/as_devices-0.18# make INSTALL_DIR=/ install

Generate doxygen documentation

  • If doxygen isn't installed on your Linux distribution, you have to install the correct package (here on *Ubuntu):
$ sudo apt-get install doxygen
  • Then go in AsDevices root directory:
$ cd target/packages/as_devices
  • Generate the documentation with Doxygen:
$ doxygen Doxyfile
  • Documentation has been generated in documentation.
    • Open documentation with:
$ firefox documentation/index.html

Using library in C

All functions in AsDevices library are constructed on the same way. An as_*_open() function return a device structure or an int that represent the device used. All function take this device structure in first parameter, and a function as_*_close() close the device :

struct as_devicename_dev * as_devicename_open(<some parameters>);

as_devicename_do-something-with-device(struct as_devicename_dev *aDev, <some parameters>);

int as_devicename_close(struct as_devicename_dev *aDev);

For each library, full documentation can be found in C header in directory target/packages/as_devices/c.

I²C

as_i2c_* functions are used to access devices on i²c bus that doesn't have/need a Linux driver. If you want to access an i²c device, please find out if a driver is not already existing before using this method.

To open the bus, you have to know its number. On APF9328 and APF27 only two busses are present: number 0 and number 1. The open() function returns an int (file descriptor of the opened /dec/i2c-x), that have to be passed to all other as_i2c_* functions :

int as_i2c_open(unsigned int i2c_id);

Then depending on the complexity of the I2C device communication protocol, you can either use read()/write() (simple frames) or ioctl() with complex "read then write"/"write then read" messages.

  • Example (simple write()):
#include <stdlib.h>
#include <stdio.h>

#include <as_devices/as_i2c.h>


int my_device = 0;
#define MY_DEV_ADDR 0x23
#define MY_I2C_BUS 1
unsigned char buf[10];
int ret;

...

my_device = as_i2c_open(MY_I2C_BUS);
if (my_device < 0) {
    printf("Can't init I2C port %d!!\n", MY_I2C_BUS);
    return -1;
}
as_i2c_set_slave(my_device, MY_DEV_ADDR);

...

buf[0] = (unsigned char) my_val;
ret = write(my_device, buf, 1);
if (ret < 0)
    printf("Error while sending data to device !!\n");

...

SPI

Usage

To use as_spi_* function, the spidev kernel module/interface is required. See SPI page to know how to configure it.

Once the device file /dev/spidevx.x is available from the kernel, as_spi library can be used by including the as_spi.h header in your C source code:

#include <as_devices/as_spi.h>

Full description of the API can be found in this header (target/packages/as_devices/c/as_spi.h), available on sourceforge repository.

Example

The three mains useful functions used to communicate with a slave SPI device are :

int as_spi_open(const unsigned char *aSpidev_name);

To open the /dev/spidevx.x special spi file. This function return a file handler that will be used for all othes as_spi_* function.

void as_spi_close(int aFd);

As its name said, to close the device.

uint32_t as_spi_msg(int aFd, 
                    uint32_t aMsg, 
                    size_t aLen,
                    uint32_t aSpeed);

This function forge spi messages on MOSI pin and return MISO message.

GPIO

Usage

To use as_gpio_* functions, the gpio kernel module is required. See GPIO_Driver page to know how to configure it.

Once the device files /dev/gpio/* are available , as_gpio library can be use by including as_gpio.h header in the C source code of your application.

#include <as_devices/as_gpio.h>

Example

Two examples are given, one for lightening led D14 and one to use blocking read on switch S1. This two example are made for APF27Dev daughter card.

  • Lightening led

With as_gpio, each pin port can be openned separately. The as_gpio_open() function returns a pointer on gpio pin structure declared like this:

 int ret; /* for returning value */
 struct as_gpio_device *pf14;

On APF27Dev, D14 is plugged on port F pin 14, then to open it :

 pf14 = as_gpio_open('F', 14);

GPIO must be configured in ouput mode :

 ret = as_gpio_set_pin_direction(pf14, "out");

Then to switch LED value, just use as_gpio_set_pin_value() function:

 ret = as_gpio_set_pin_value(pf14, 1); /* led off */
 ...
 ret = as_gpio_set_pin_value(pf14, 0); /* led on */

Note that because off led wiring, led polarity is inverted (to light on set 0).

Once gpio pin usage is terminated, it must be closed :

 as_gpio_close(pf14);
  • Pressing button

The button S1 can be used to test interrupt capability of gpio. The button is plugged on gpio port F pin 13. After declaring the as_gpio_device structure, the pin port can be opened :

 struct as_gpio_device *pf13;
 [...]

 pf13 = as_gpio_open('F', 13);

To stuff must be configured before using it as interruption source, direction and IRQ mode.

direction

 ret = as_gpio_set_pin_direction(pf13, "in"); /* set switch as input */

IRQ mode There is four IRQ mode :

  • GPIO_IRQ_MODE_NOINT : No interrupt, the processor will ignore event on this gpio.
  • GPIO_IRQ_MODE_RISING : rising edge, the processor will generate an interruption on rising edge of gpio pin.
  • GPIO_IRQ_MODE_FALLING: falling edge, the processor will generate an interruption on falling edge of gpio pin.
  • GPIO_IRQ_MODE_BOTH : both, the processor will generate an interruption on both rising or falling edge of gpio.
 ret = as_gpio_set_irq_mode(pf13, GPIO_IRQ_MODE_FALLING); /* interrupt will be generated on pushed button */

To capture interruption, the blocking read function can be used with a timeout. If no interruption is raised after the timeout time, read function end with error value -10.

 ret = as_gpio_blocking_get_pin_value(pf13, 3, 0); /* wait for interruption for 3 seconds and 0 µs) */
 if(ret == -10)
     printf("Timeout\n");

ADC

MAX1027

AS1531

DAC

MAX5821

MCP4912

93LCXX

PWM

Usage

To use as_pwm_* functions, the kernel module imx_pwm needs to be loaded. See PWM page to know how to configure it.

Once the special files /sys/class/pwm/pwmX/* are available , as_pwm_* functions can be use by including as_pwm.h header in the C source code of your application.

#include <as_devices/as_pwm.h>

Example

#include <as_devices/as_pwm.h>
...

int main(int argc, char *argv[])
{
    struct as_pwm_device *my_pwm;
...
    my_pwm = as_pwm_open(0);
    if (!my_pwm)
        printf("Can't init PWM !!\n");
    as_pwm_set_frequency(my_pwm, 150);
    as_pwm_set_duty(my_pwm, 500);
...
    as_pwm_set_state(my_pwm, 1);
}

LED

Using library in Python

To use AsDevices in Python, select the python wrapper in menuconfig as follow :

Package Selection for the target  --->
  *** Armadeus specific packages ***
  Armadeus specific tools/utilities  --->   
    [*] as_devices 
    [*]   wrapper Python

And keep all .py file on target :

Package Selection for the target  --->
    Interpreter languages and scripting  --->
        python module format to install (.py sources and .pyc compiled)  --->
            (X) .py sources and .pyc compiled

then compile bsp and flash it on your board.

Once done, just import the module AsDevices to use all function available in library:

import AsDevices
from AsDevices import AsGpio

gpio = AsGpio(3)
gpio.setPinDirection('out')
gpio.setPinValue(1)
...

Using library in C++

SPI

  • Open the spidev device given in parameters and send one byte message:
#include <iostream>

#include <as_devices/cpp/as_spi.hpp>

//#define APF_SPI       "spidev1.2" on APF27
#define APF_SPI "spidev1.1" // on APF9328
#define CLOCK_SPEED     1200000

using namespace std;

int main(int argc, char **argv)
{
        const unsigned char* spidev_name = (const unsigned char*) APF_SPI;

        if (argc > 1) {
                spidev_name = (const unsigned char*) argv[1];
        }
        cout << "Opening " << spidev_name << endl;
        AsSpi* o=new AsSpi(spidev_name);

        int speed = o->getSpeed();
        cout << "Max speed =" << speed << endl;

        int mode = o->getMode();
        cout << "Mode = " << mode << endl;

        char data = 'c';
        unsigned long long result = o->msg((unsigned long long) data, sizeof(data), CLOCK_SPEED);
        cout << "result=" << result << endl;

        return 0;
}
  • Makefile:
CFLAGS = -I/home/xxx/buildroot/output/staging/usr/include/as_devices
CFLAGS += -I/home/xxx/buildroot/output/staging/usr/include/as_devices/cpp

LDFLAGS = -L/home/xxx/buildroot/output/staging/usr/lib
LDFLAGS += -las_devices_cpp -las_devices

EXEC_NAME = foo

all: $(EXEC_NAME)

$(EXEC_NAME): foo.cpp
        $(CXX) $(CFLAGS) $(LDFLAGS) -Wall -o $@ $^

clean: 
        rm -rf $(EXEC_NAME)
        rm -rf *.o

.PHONY: clean

OTHER -> TODO

Development planning

AsDevices is not finished, following table indicates the remaining work:

Name Component C functions C++ wrapper Python wrapper Python class description
i2c Ok Ok NOK NOK Drive I2C
spi Ok, but not fully tested Ok, but not fully tested Ok, but not fully tested Ok, but not fully tested Drive SPI
gpio Ok Ok Ok Ok Drive GPIO
ADC max1027 Ok for SLOW mode Ok NOK NOK
as1531 Ok for SLOW mode Ok NOK NOK
lradc Ok for SLOW mode Ok NOK NOK
DAC max5821 OK Ok, but not fully tested NOK NOK
mcp4912 NOK Ok NOK NOK
eeprom 93LCxx OK OK NOK NOK
PWM OK OK NOK NOK
Backlight OK OK NOK NOK
LED Ok NOk NOk NOk Drive LED
BMP180 NOk NOk NOk OK
HMC5883 NOk NOk NOk OK

Links

  • libsoc is a project similar to AsDevices.
  • WiringPi is a project similar to AsDevices for RPi.On OPOS6ULDev, AsDevices provides WiringPi emulation.