Difference between revisions of "AsDevices"
(→I²C) |
(→Development planning) |
||
(43 intermediate revisions by 6 users not shown) | |||
Line 1: | Line 1: | ||
− | |||
− | AsDevices is an | + | 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". | + | 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 | + | {{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 | + | The library is included in Buildroot menu, to use it just select it (if not already installed on your target, like on [[OPOS6UL]]): |
− | + | <pre class="host"> | |
+ | $ make menuconfig | ||
+ | </pre> | ||
<pre class="config"> | <pre class="config"> | ||
− | + | ... | |
− | + | Target packages ---> | |
− | + | ... | |
− | + | Armadeus specific tools/utilities ---> | |
− | + | ... | |
− | + | [*] 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). |
− | + | * Rebuild all: | |
+ | <pre class="host"> | ||
+ | $ make | ||
+ | </pre> | ||
+ | * Then reflash your rootfs | ||
+ | ===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 ? ;-) | ||
+ | root@opos6ul:~/as_devices-0.18# make INSTALL_DIR=/ install | ||
+ | </pre> | ||
+ | |||
+ | == 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 == | == Using library in C == | ||
Line 41: | Line 76: | ||
=== I²C === | === I²C === | ||
− | as_i2c_* functions are used to access | + | 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 | + | 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"> | <source lang="C"> | ||
int as_i2c_open(unsigned int i2c_id); | int as_i2c_open(unsigned int i2c_id); | ||
+ | </source> | ||
+ | |||
+ | 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()): | ||
+ | |||
+ | <source lang="C"> | ||
+ | #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"); | ||
+ | |||
+ | ... | ||
</source> | </source> | ||
=== SPI === | === SPI === | ||
− | To use as_spi_* function, the kernel module | + | ==== Usage ==== |
+ | To use as_spi_* function, the ''spidev'' kernel module/interface is required. See [[SPI]] | ||
page to know how to configure it. | page to know how to configure it. | ||
− | Once the | + | 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: |
− | library can be used including the | + | |
<source lang="C"> | <source lang="C"> | ||
− | #include | + | #include <as_devices/as_spi.h> |
</source> | </source> | ||
− | Full description of the API can be found in this header, available on | + | Full description of the API can be found in this header (target/packages/as_devices/c/as_spi.h), available on |
− | [http:// | + | [http://sourceforge.net/p/armadeus/code sourceforge repository]. |
− | + | ||
+ | ==== Example ==== | ||
− | The three mains | + | The three mains useful functions used to communicate with a slave SPI device |
are : | are : | ||
Line 89: | Line 161: | ||
This function forge spi messages on MOSI pin and return MISO message. | This function forge spi messages on MOSI pin and return MISO message. | ||
+ | |||
=== GPIO === | === GPIO === | ||
− | |||
+ | ==== Usage ==== | ||
− | === MAX5821 === | + | 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 === | === 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 104: | 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 !! | + | ! Name !! Component !! C functions !! C++ wrapper !! Python wrapper !! Python class !! description |
|- align="center" | |- align="center" | ||
− | | [[I2C | i2c]] || bgcolor="green"| Ok || bgcolor=" | + | | [[I2C | i2c]] || || bgcolor="green"| Ok || bgcolor="green"| Ok ||bgcolor=#FF0000| NOK ||bgcolor=#FF0000| NOK || Drive I2C |
|- align="center" | |- align="center" | ||
− | | [[SPI | spi]] || bgcolor="green" | Ok, not fully tested || bgcolor= | + | | [[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" | ||
− | | [[Gpio | gpio]] || bgcolor="green"| Ok || bgcolor=" | + | | [[Gpio | gpio]] || || bgcolor="green"| Ok || bgcolor="green"| Ok ||bgcolor="green" | Ok ||bgcolor="green" | Ok || Drive GPIO |
|- align="center" | |- align="center" | ||
− | | [[ADC_max1027 | max1027]] || bgcolor="green"| Ok for SLOW mode ||bgcolor= | + | | 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" | ||
− | | [[ | + | | [[as1531 | as1531]] || bgcolor="green"| Ok for SLOW mode ||bgcolor="green"| Ok ||bgcolor=#FF0000| NOK ||bgcolor=#FF0000| NOK || |
|- align="center" | |- align="center" | ||
− | | | + | | [[lradc | lradc]] || bgcolor="green"| Ok for SLOW mode ||bgcolor="green"| Ok ||bgcolor=#FF0000| NOK ||bgcolor=#FF0000| NOK || |
|- align="center" | |- align="center" | ||
− | | [[PWM]] || bgcolor="green" | OK || bgcolor=" | + | | rowspan="2" | DAC |
+ | | [[Max5821 | max5821]] || bgcolor="green"| OK ||bgcolor="green"| Ok, but not fully tested ||bgcolor=#FF0000| NOK ||bgcolor=#FF0000| NOK || | ||
+ | |- align="center" | ||
+ | | [[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" | ||
|} | |} | ||
+ | |||
+ | == 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: This library is under development, see the Development planning to know which functionality is completed. |
Contents
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 |