viernes, 26 de julio de 2013

Compilación cruzada para Raspberry Pi desde Windows [II]: la librería BCM2835

El BCM2835 es un procesador orientado a aplicaciones multimedia, móviles y/o embebidas, y que resultó ser el de elección en el diseño de los sistemas Raspberry Pi. Mike McCauley ha elaborado una librería (http://www.airspayce.com/mikem/bcm2835/) para exponer fácil y elegantemente al programador los mecanismos de entrada y salida (IO) hardware de este procesador, y del que un subconjunto importante de ellos son físicamente accesibles de forma directa en el conector P1 de la RPi (para mayor información sobre este tema, ver http://elinux.org/RPi_Low-level_peripherals).

La instalación de la librería es muy sencilla bajo Linux. Copiando el procedimiento que se aporta en la página web de la librería, tenemos: 

# download the latest version of the library, say bcm2835-1.xx.tar.gz, then: 
tar zxvf bcm2835-1.xx.tar.gz 
cd bcm2835-1.xx 
./configure 
make 
sudo make check 
sudo make install 

Pero este es el procedimiento para su instalación en Linux-Raspbian, mientras que nuestro objetivo es atacar esta librería bajo Windows. La solución no es complicada. 

Para lograr lo anterior nos interesan dos ficheros en particular de la librería: 

 • bcm2835.h: este header acompaña a las fuentes de la librería. Como toda cabecera C, declara variables y funciones que serán utilizadas para lograr los objetivos que se proponen en la librería. En los programas que diseñemos que deban acceder a los GPIOs de la RPi haciendo uso de esta librería, deberemos incluir obligatoriamente este header mediante #include &#60bcm2835.h&#62.

libbcm2835.a: la librería propiamente dicha, y que se trata del fichero obtenido una vez compilada. Por su extensión (.a) ya sabemos que no es compartida (estática, por tanto), en contraposición a las librerías compartidas (o dinámicamente enlazadas) con extensión .so. Las variables y funciones de la librería, declaradas en bcm2835.h según ya hemos visto, serán accesibles en nuestros programas tras la inclusión de la cabecera comentada en el punto anterior. 

Mientras que el primero, bcm2835.h, ya lo podemos obtener del código fuente de la librería, el segundo lo obtendremos tras su compilación. Así que procederemos a descargar en nuestra Raspberry Pi, y por el procedimiento que entendamos conveniente, la última versión de la librería, sobre la que aplicaremos el procedimiento visto más arriba. Si estamos trabajando en el entorno Windows, manteniendo la RPi conectada a la misma red local que nuestro PC, podremos usar las opciones de transferencia de ficheros de SmarTTY. En particular, y tras descargar la librería a un directorio temporal de Windows, elegimos o creamos en el terminal conectado a nuestra RPi el directorio de descarga, nos situamos en él, y arrastramos a la pantalla del terminal el fichero en cuestión. Una vez en Raspbian, aplicamos el procedimiento de instalación, que en nuestro caso resultó completamente transparente y eficaz. 

Tras la instalación, el proceso habrá creado el directorio /bcm2835-1.xx/src, donde encontraremos, entre otros objetos, la librería creada libbcm2835.a, además de una copia de bcm2835.h. Por un mecanismo de transferencia recíproco al ya visto, copiaremos estos ficheros a Windows, para lo que podemos utilizar la utilidad Upload a file del menú SCP de SmarTTY. Estos ficheros, una vez en Windows, los añadiremos a los directorios de la toolchain GNU. Por ejemplo, y asumiendo que a la instalación de la toolchain hemos respetado los directorios de destino propuestos, podemos copiarlos en: 

 • bcm2835.h -> C:\SysGCC\Raspberry\lib\gcc\arm-linux-gnueabihf\4.6\include 

libbcm2835.a -> C:\SysGCC\Raspberry\lib\gcc\arm-linux-gnueabihf\4.6 

Existen otras combinaciones de archivado, pero esta propuesta funciona. 

Y ya está: hemos incluido en nuestro entorno el acceso a la librería bcm2835, que nos permitirá gestionar el conjunto de pins IO del procesador BCM2835, habilitando funciones extra propias de sistemas embebidos y cuya descripción ocuparía otro post. 

Pedimos prestado el código de ejemplo de la librería para encender y apagar un led, el blink que en todo sistema embebido constituye el "hola, mundo", y lo transcribimos para analizarlo someramente: 

// blink.c 
// 
// Example program for bcm2835 library 
// Blinks a pin on an off every 0.5 secs 
// 
// Author: Mike McCauley 
// Copyright (C) 2011 Mike McCauley 
// $Id: RF22.h,v 1.21 2012/05/30 01:51:25 mikem Exp $ 

#include &#60bcm2835.h&#62
// Blinks on RPi Plug P1 pin 11 (which is GPIO pin 17) 
#define PIN RPI_GPIO_P1_11 

int main(int argc, char **argv) 
{ 
    // If you call this, it will not actually access the GPIO 
    // Use for testing 
    // bcm2835_set_debug(1); 
    if (!bcm2835_init()) 
    return 1
    // Set the pin to be an output 
    bcm2835_gpio_fsel(PIN, BCM2835_GPIO_FSEL_OUTP); 
    // Blink 
    while (1) 
    { 
        // Turn it on 
        bcm2835_gpio_write(PIN, HIGH)
        // wait a bit 
        bcm2835_delay(500)
        // turn it off 
        bcm2835_gpio_write(PIN, LOW)
        // wait a bit 
        bcm2835_delay(500)
    } 
    bcm2835_close()
    return 0
} 

En primer lugar, a destacar la inclusión del header que nos permitirá acceder a la librería. Inmediatamente después, y por comodidad, definimos PIN como sinónimo de la declaración del pin 11 del conector P1 de la RPi, que en realidad corresponde al GPIO número 17 del procesador. 

Ya en main() hacemos varias cosas: 

1 - Activamos la librería mediante bcm2835_init(), sentencia obligatoria en todo código que quiera hacer uso de la misma. En general, el nombre de las funciones y variables de la librería utilizan el prefijo bcm2835_ como indicador de su espacio de nombres. 

2 - Configuramos el pin que hemos denominado PIN como de salida mediante la función bcm2835_gpio_fsel(), cuyos parámetros son autoexplicativos. 

3 - Y entramos, finalmente, en un bucle sin fin que pone a alto el pin en cuestión (por lo que se activará en el mismo una tensión de 3,3 voltios que puede encender un led conectado entre el pin y masa; ojo a la polaridad); espera medio segundo (aproximadamente: no estamos ante un sistema operativo de tiempo real); cancela la tensión en el pin poniéndolo a bajo; y espera otro medio segundo antes de volver a comenzar el bucle. 

Al final del código vemos una sentencia que proporciona un cierre ordenado de las funciones de la librería, bcm2835_close(), que es conveniente aplicar en la salida de todo código que la gestione, pero que en este ejemplo en particular no se llega a ejecutar nunca dado el ámbito temporal sin fin del bucle. 

Para la compilación del código podemos ejecutar en la consola de Windows, y dentro de la toolchain instalada, el siguiente comando: 

c:\ruta_de_acceso_a_toolchain\arm-linux-gnueabihf-g++.exe c:\ruta_de_acceso_a_fuentes\blink.c -o c:\ruta_de_acceso_a_compilaciones\blink 

tras el cual obtendremos el fichero ejecutable blink en el mismo directorio donde reside el código fuente. Obviamente tendremos que modificar las rutas de acceso a cada uno de los ficheros de acuerdo al esquema de nuestro propio sistema, u omitirlas siempre que cumplamos las reglas de acceso a los ficheros del sistema operativo o estén registradas en la variable de entorno de Windows PATH

El producto obtenido lo transferimos a nuestra Raspberry Pi. Seguramente nos resultará más cómodo utilizar las utilidades correspondientes del menú SCP de SmarTTY, o simplemente arrastrar el icono del archivo compilado a la ventana del terminal conectado a la RPi. 

Una vez en Linux/Raspbian, hay que dotarlo de los permisos necesarios para su ejecución mediante chmod a+x blink, para ejecutarlo a continuación mediante sudo ./blink.  Nótese la necesidad de ejecutar bajo root (si no es el usuario activo) con sudo, ya que se exigen sus privilegios para acceder a este hardware. 

Para los que se sientan cómodos con el trabajo mediante la consola de Windows (y, probablemente, con proyectos de muy pequeña envergadura), el trabajo termina aquí. Tenemos la toolchain funcionando, incluyendo la librería de ataque al hardware IO de la RPi, y un terminal muy útil como es SmarTTY apoyándonos en todo el trabajo de comunicación con (y de la gestión de) la placa. Para los que prefieran un entorno más amigable y productivo de programación, aún tendremos algunos ajustes adicionales. Merecerán la pena.

No hay comentarios: