martes, 11 de junio de 2013

MATERIALES DE BRICO HARDWARE

Hay una serie de materiales bastante útiles cuando comenzamos a trabajar con la GPIO de la Raspberry Pi, en esta entrada, voy a comentar algunos de ellos.

PLACA DE PRUEBAS, PROTOBOARD O BREADBOARD

La placa de pruebas permite la construcción de prototipos electrónicos, ya que su forma, tablero lleno de orificios conectados en línea, facilita la conexión de cables y dispositivos.

En particular, la placa con la que se ha trabajado tiene dos líneas verticales, positiva y negativa en cada extremo. A la línea positiva se conectará la línea de 3v3 o 5v de la Raspberry Pi y a la negativa la línea de tierra o ground (gnd), a estas líneas se conectarán otras cables para realizar circuitos.

Además hay en el medio dos bancadas de 63 líneas verticales, cuyos orificios quedan identificados por una columna, que tiene asignada una letra y una fila, que tiene asociado un número. Cada una de las filas está conectada entre sí, hasta que llega al salto que se encuentra entre las columnas e y f. Por ejemplo, todos los dispositivos que se conectan en la cuarta línea entre las columnas a y e están conectados.


CABLEADO

El cableado utilizado en la protoboard tiene la particularidad de que no es necesario soldar nada (solderless), hay de varias longitudes.


CINTA PARA LA GPIO

La opción más cómoda para trabajar es llevar toda la GPIO a la protoboard, para ello es necesario utilizar una cinta que conecte los pines de la GPIO.


CONECTOR GPIO A LA PROTOBARD

En el punto anterior, al analizar la cinta GPIO, se ha observado que los conectores son hembra, por tanto, es necesario utilizar un adaptador para conectar la cinta a la protoboard. El conector que se ha utilizado es bastante cómodo ya que aparece la descripción de cada uno de los pines GPIO.



MULTÍMETRO

Se ha utilizado un multímetro para estudiar si los voltajes proporcionados por la Raspberry Pi son correctos.

RESISTENCIAS

Las resistencias son necesarias para evitar fundir algunos componentes, tales como LED ó 7 segmentos. Las magnitudes que identifican a  las resistencias son la resistencia eléctrica, disipación máxima y precisión, dicha información, se puede obtener de los colores que están presentes en el encapsulado. La unidad empleada en medir resistencias son los ohmios (Ω).

A continuación, se mostrará una tabla en la que se identifican colores y sus valores respectivos, las tres primeras bandas hacen referencia al valor de la resistencia y la cuarta la tolerancia. 

Color
Valor
Tolerancia
Negro
0
-
Marrón
1
±1%
Rojo
2
±2%
Naranja
3
-
Amarillo
4
±4%
Verde
5
±0,5%
Azul
6
±0,25%
Morado
7
±0,1%
Gris
8
±0.05%
Blanco
9
-
Dorado
-
±5%
Plateado
-
±10%

Si se considera una resistencia que presenta los siguientes colores Marrón (1) - Negro (0) –Naranja (3) –Dorado( ±5% ), el valor de la resistencia es 10.000 Ω = 10 k Ω

POTENCIÓMETRO

Este componente se ha utilizado básicamente con la pantalla LCD, ya que permite regular la intensidad del voltaje. La parte superior “gira” de tal manera que deja pasar más o menos voltaje. La conexión a la protoboard debe realizarse de tal manera que dos patas inferiores caigan en una línea y la pata superior caiga en otra línea.



PROGRAMANDO GPIO


Se han programado los pines de la GPIO básicamente de tres maneras, por una parte, mediante sysfs, por otra mediante el comando gpio que procede de la librería wiringPi y hasta que no la instalemos no está disponible y la tercera manera es a través de la librería wiringPi, que ya ha sido comentada en una entrada anterior.
Comando gpio
Este comando está operativo a partir de la instalación de la librería wiringPi.
Se pueden realizar la mayor parte de las operaciones que se han especificado en la librería de C directamente en línea de comandos, mediante la herramienta gpio.
  • -v muestra la versión
  • –g especifica que la numeración de pines es BCM GPIO
  • mode n [ in| out | pwm ] establece pin n en modo entrada, salida o pwm, respectivamente.
  • mode n [ up | down |tri  ] configura las resistencias del pin n en modo subida, bajada o ninguno.
  • read n lee el valor del pin n.
  • readall lee todos los valores posibles y los muestra por pantalla.
  • write n [ 1 | 0 ] escribe en el pin n un valor 1 (HIGH) o 0 (DOWN).
  • pwm n value establece en el pin n el valor value.
  • edge n [ rising | falling | both | none ] permite configurar las interrupciones sobre el pin n como flanco de subida, bajada, ambos o ninguno.
  • export n [ in| out ] exporta el pin n para que pueda ser utilizado por otros programas que no son lanzados por root.
  • exports muestra una lista de todos los pines que han sido exportados.
  • unexport n el pin n deja de estar disponible para programas que no han sido ejecutados por root.
  • unexportall idéntico al anterior pero para todos los pines.
  • load spi [buffer size ] Carga los módulos SPI en el kernel y establece opcionalmente un buffer definido en KB, yo valor por defecto es 4 KB.
  • load i2c [baud rate] Carga los módulos I2C en el kernel y establece opcionalmente la proporción en baudios en KB/s, cuyo valor por defecto es 100Kb/sec.
Interfaz sysfs
El sistema operativo Raspbian tiene mapados los pins de la GPIO en /sys/class/gpio, para poderlos gestionar a través de los ficheros que se encuentran en dicho directorio, export, unexport y el enlace simbólico a ../../devices/virtual/gpio/gpiochip0.
Para poder utilizar un pin, se debe escribir en el fichero export, su número. Hay que tener en cuenta que sólo root puede realizarlo (sudo su), para ello normalmente se utiliza el comando echo (echo n > /sys/class/gpio/export , donde n es el pin). A continuación se crea automáticamente un enlace simbólico en el mismo directorio al dispositivo virtual (../../devices/virtual/gpio/gpion). El pin se deberá establecer como de entrada o salida (echo out | in  > /sys/class/gpio/gpion/direction). En el caso de ser de salida, se puede establecer la salida a 1 o 0 (echo 1 | 0  > /sys/class/gpio/gpion/value). En el caso de ser de entrada, se podría comprobar su valor en un fichero ( cat /sys/class/gpio/gpion/value ). 
Finalmente, hay que dejar accesibles estos ficheros para otras aplicaciones, ya que cuando exportamos, los estamos bloqueando.
A continuación, se expone como se podría enceder un led asociado al pin n.
echo n > /sys/class/gpio/export
echo out > /sys/class/gpio/gpion/direction
echo 1 > /sys/class/gpio/gpion/value
echo n > /sys/class/gpio/unexport

VOLTAJES EN LA RASPBERRY PI

La alimentación en la Raspberry Pi se realiza mediante una conexión micro USB, similar al que utilizan la mayor parte de los cargadores de los Smartphones actuales.
Para comprobar si el suministro eléctrico es correcto, dentro de la placa se encuentran dos puntos TP1 (Positivo) y TP2, (Negativo). Cuando se mide la corriente con un multímetro en posición de Corriente Continua y escala de 20V, debe ofrecer un resultado similar a 5V.
MEDICIÓN TP1  y TP2

Dentro de los pines GPIO hay dos que dan de manera continua 5V y 3.3V, que son especialmente útiles para probar circuitos. En la imagen inferior, los localizamos en las posiciones 1 y 2, mientras que tierra es el 6.
PINES GPIO RASPBERRY PI V 2.0.

MEDICIÓN DE LOS PINES DE 3.3V

MEDICIÓN DE 5V

Si que habrá que tener en cuenta en futuras experienias, que hay que tener especial cuidado con el consumo de los dispositivos que se conectan a través de GPIO, en concreto, la máxima intensidad demandada por los dispositivos puede ser de 300 mA (1000mA - 700mA). En caso de sobrepasar esos límites, seguramente estropearemos la placa.

lunes, 10 de junio de 2013

CONFIGURANDO ACCESO REMOTO


Para facilitar el trabajo sobre Raspberry Pi y poder trabajar directamente sobre ella desde otro equipo, veremos diferentes opciones y herramientas, concretamente, SSH para trabajar en línea de comandos, un cliente de Escritorio Remoto como TightVNC y Samba, para poder dejar en una carpeta compartida nuestros programas y scripts.
Lo primero que deberíamos hacer si no lo hemos hecho ya es configurar una dirección IP fija, tal y como se ha mostrado en la entrada "INSTALANDO Y CONFIGURANDO RASPBIAN".
Para trabajar sobre SSH tenemos dos opciones, habilitar mediante "raspi-config" el equipo como servidor de SSH ó instalarlo en línea de comandos (sudo apt-get install openssh-server).
Una vez instalado el servidor de SSH el siguiente paso será conectarnos mediante un cliente, como puede ser Putty.
Para conectarse mediante Putty el primer paso será descargarlo (Download).
El siguiente paso será configurarlo y ejecutarlo. Para evitar tener que poner todos los datos cada vez que nos conectemos, pondremos los datos de la dirección IP y guardaremos la sesión (Save), en mi caso se he llamado "Raspberry Pi". Ahora ya nos podremos conectar (Open).
Alerta inicial la primera vez que nos conectamos
Introducimos el nombre de Usuario pi y contraseña raspberry
ESCRITORIO REMOTO (TIGHTVNC)
Con el objetivo de realizar conexiones de Escritorio desde múltiples Sistemas Operativos, se ha optado por el software gratuito y libre “TightVnc” .
El primer paso es instalar el programa en nuestra RPI, para ello, partiremos de que se puede realizar una conexión mediante SSH (no es necesario pero si solivianta estos pasos repetitivos), a continuación se deben actualizar los repositorios (sudo apt-get update) y proceder con la instalación (sudo apt-get install tightvncserver), aceptando el mensaje que muestra.
Una vez instalado el programa nuestro equipo será un "servidor" que aceptará conexiones de escritorio remoto. Ahora, para poder realizar una conexión habrá que realizar una instancia en el servidor para podernos conectar desde otro equipo. Un ejemplo de instancia podría ser vncserver :1 -geometry 1024x768 -depth 24, estamos configurando la instancia 1, con una resolución de 1024x768 y una profundidad de color de 24 bit. A continuación pedirá la contraseña de conexión para los clientes.
En mi caso la contraseña seleccionada ha sido raspberry, para acordarme posteriormente.
El principal problema es que cada vez que reiniciamos esta instancia se pierde.
En este punto, podemos conectarnos mediante clientes de VNC. En la página http://www.tightvnc.com/ podremos encontrar varios clientes, si bien el Viewer de Java ha presentado problemas debido a un bug de representación de caracteres, por ello, se ha trabajado principalmente con un portable que no ha dado problemas (http://www.tightvnc.com/download/1.3.10/tightvnc-1.3.10_x86_viewer.zip).
Para conectarnos debemos indicar la dirección ip y el puerto. El puerto por defecto es 5900 pero hay que sumar el número de conexión que es 1.
En este punto debemos indicar la conexión citada anteriormente
En este punto debemos indicar la conexión citada anteriormente y ya podemos trabajar en entorno gráfico.
Fácilmente se puede configurar una aplicación similar para Android denominada VNCAndroid y trabajar mediante el móvil, es decir, !tenemos totalmente contralada la Raspberry Pi con el móvil!.
En este punto habría que preguntarse, ¿no resulta demasiado pesado tener que crear la instancia antes de conectarse?. Existe una solución que es crear un demonio que arranque al principio.
En primer lugar hay que comentar que hay siete modos de ejecución, cada uno de estos modos de ejecución X ejecuta varios scripts. En los directorios/etc/rcX.d/ se encuentran los enlaces simbólicos que se ejecutarán en el modo de ejecución X y , generalmente, estos scripts se almacenan en el directorio /etc/init.d.
En Raspbian el nivel en el que se arranca por defecto es 2, para saberlo es tan sencillo como ejecutar el comando runlevel.
En es este punto donde se debe crear un fichero que contenga el contenido que va a ejecutar el demonio, que se denominará remoto (descargary contendrá la configuración.
#!/bin/bash
### BEGIN INIT INFO
# Provides: remoto
# Required-Start: $syslog
# Required-Stop: $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: vnc server
# Description: Demonio Servidor Escritorio Remoto VNC
#
### END INIT INFO
## Autor: M.Alvarez (miguelwarez@gmail.com) 2013
## Más ejemplos en http://rpiplus.sourceforge.net


PROG="Xtightvnc"

case "$1" in
start)
echo "Lanzando $PROG"
su pi -c '/usr/bin/vncserver';;
stop)
echo "Parando $PROG"
pkill -TERM $PROG;;
reload)
echo "Volviendo a cargar $PROG:"
pkill -HUP $PROG;;
restart)
echo "Reiniciando $PROG"
pkill -TERM $PROG
su pi -c '/usr/bin/vncserver';;
*)
echo "Uso: /etc/init.d/remoto {start|stop|reload|restart}"
exit 1;;
esac
exit 0 
Definimos un demonio que se puede lanzar (start), parar(stop), reload (volver a cargar), restart (reiniciar), utilizando básicamente las señales disponibles de LINUX.
Ya sólo falta dar permisos de ejecución al fichero para todos los usuarios, para ello se ha utilizado el comando chmod.
A continuación se dejará el fichero en el directorio donde se encuentran los demonios que ejecuta Raspbian.
A continuación, se van a actualizar los scripts mediante el comando update-rc.d
Se va a comprobar el correcto funcionamiento, lanzando el demonio y parándolo.
Además para comprobar que se ha creado correctamente el enlace simbólico:
Ahora ya está configurada Raspberry Pi para que cada vez que se encienda nos podamos conectar mediante escritorio remoto.
INSTALACIÓN DE SAMBA
Especialmente útil resultará tener instalado samba para poder conectarnos a una carpeta compartida en la que dejemos los programas y scripts.
Para instalar samba y un cliente deberemos ejecutar sudo apt-get install samba smbclient.
Se va a definir una carpeta compartida publica que se encontrará en el home de pi y no será visible en la red. El primer paso es crear una carpeta denominada publica con todos los permisos: mkdir -m 777 publica.
Posteriormente, se editará el fichero /etc/samba/smb.conf y se añadirá al final:
[publica$]
path = /home/pi/publica
browseable = yes
writeable = yes
guest ok = yes
Para concluir se deberá reiniciar el servicio samba, para que cargue la nueva configuración sudo /etc/init.d/samba restart.
En este momento se podrá acceder desde cualquier equipo a esta carpeta escribiendo \\dirIP\publica$
Al trabajar con Sistemas Operativos Windows y Linux se han constado errores al ejecutar shell scripts del  tipo:
bash: ./mifichero.sh: /bin/bash^M: bad interpreter: No existe el fichero o el directorio
Estos errores se deben a que en los Sistemas Operativos Windows, se insertan al final de cada línea retornos de carro y saltos de línea, mientras que en Linux se insertan sólo saltos de línea.
Para eliminar este tipo de errores se ha optado por el programa dos2unix, que elimina este tipo de problemas, convirtiendo de Dos a Unix como su nombre indica. La sintaxis es dos2unix mifichero.sh. Si tenemos problemas con el propietario, mediante el comando sudo chown pi mifichero.sh cambiaremos el propietario y ya podremos pasar el comando sin problemas.

domingo, 9 de junio de 2013

EXPLORANDO EL HARDWARE DE RASPBERRY


Esta entrada se va a realizar un análisis del hardware de la Raspberry Pi, partiendo de las especificaciones técnicas de la Raspberry Pi B modelo 2.0. Para realizar el estudio se partirán de herramientas incluidas en el Sistema Operativo y alguna otra que habrá que instalar.
La información sobre el Hardware del equipo se va a obtener del directorio /proc , sistema de ficheros virtual que el sistema crea en memoria y ofrece información relacionada con el sistema.
El primer fichero que se va a analizar es /proc/cpuinfo, que tiene información relativa al procesador.  Una vez ejecutado cat /proc/cpuinfo obtenemos la siguiente información
Processor       : ARMv6-compatible processor rev 7 (v6l)
BogoMIPS        : 697.95
Features        : swp half thumb fastmult vfp edsp java tls
CPU implementer : 0x41
CPU architecture: 7
CPU variant     : 0x0
CPU part        : 0xb76
CPU revision    : 7
Hardware        : BCM2708
Revision        : 000f
Serial          : 00000000c047d6ab
La información más importante que se puede observar es la versión de procesador ARM con la que es compatible con la versión 7, identificado por BCM2708 (procesador Broadcom 2708).
Mediante el comando lscpu se obtiene:
Architecture:          armv6l
Byte Order:            Little Endian
CPU(s):                1
On-line CPU(s) list:   0
Está indicando que solo hay una CPU y utiliza el sistema Little-Endian, es decir, el acceso a los bytes se realiza de manera incremental, de menos relevante a más relevante.
Para explorar la memoria se va a explorar el archivo /proc/meminfo, que contiene información del sistema de memoria. Para acceder a su contenido cat /proc/meminfo.
MemTotal:         448996 kB
MemFree:          251624 kB
Buffers:           38624 kB
Cached:           107892 kB
SwapCached:            0 kB
Active:            88828 kB
Inactive:          85020 kB
Active(anon):      27400 kB
Inactive(anon):      724 kB
Active(file):      61428 kB
Inactive(file):    84296 kB
Unevictable:           0 kB
Mlocked:               0 kB
SwapTotal:        102396 kB
SwapFree:         102396 kB
Dirty:                 0 kB
Writeback:             0 kB
AnonPages:         27344 kB
Mapped:            17100 kB
Shmem:               796 kB
Slab:              18452 kB
SReclaimable:      14840 kB
SUnreclaim:         3612 kB
KernelStack:        1168 kB
PageTables:         1396 kB
NFS_Unstable:          0 kB
Bounce:                0 kB
WritebackTmp:          0 kB
CommitLimit:      326892 kB
Committed_AS:     153780 kB
VmallocTotal:     188416 kB
VmallocUsed:         884 kB
VmallocChunk:     186712 kB
Estos datos indican que la memoria RAM es de 438 MB, prácticamente la memoria del sistema está libre, unos 38 MB están siendo utilizados por buffers en este momento, unos 107 MB se están utilizando de memoria RAM como Caché, no hay Caché en al memoria virtual, se están utilizando 102 MB como memoria virtual (SWAP).
En este punto cabría preguntarse cómo puede ser que se comercialice la placa con 512 MB de RAM  cuando el sistema muestra un valor bastante inferior cercano de unos 438 MB. Esto es debido a que a los 512 MB se les quita unos pocos bits reservados y espacio del kernel.
Información similar pero más resumida se obtiene mediante el comando free –m .
total

used
free
shared
buffers
cached
Mem:
438
116
321
0
12
68
-/+
buffers/cache:
35
402
Swap:
99
0
99

Para explorar la memoria dedicada a cada dispositivo físico se explora el fichero /proc/iomem.
00000000-1bffffff : System RAM
  00008000-004c0e77 : Kernel text
  004e2000-005b5127 : Kernel data
20000000-20000fff : bcm2708_vcio
20003000-20003fff : bcm2708_systemtimer
20006000-20006fff : bcm2708_usb
  20006000-20006fff : dwc_otg
20007000-20007fff : bcm2708_dma.0
  20007000-20007fff : bcm2708_dma
20100000-201000ff : bcm2708_powerman.0
20200000-20200fff : bcm2708_gpio
20201000-20201fff : dev:f1
  20201000-20201fff : uart-pl011
20204000-202040ff : bcm2708_spi.0
20205000-202050ff : bcm2708_i2c.0
20300000-203000ff : bcm2708_sdhci.0
  20300000-203000ff : mmc0
20804000-208040ff : bcm2708_i2c.1
20980000-2099ffff : bcm2708_usb
  20980000-2099ffff : dwc_otg
En este punto se ven las zonas de memoria para la comunicación con dispositivos a través de la GPIO, USB, serie,...
Existe un fichero bastante interesante que se encuentra en /boot denominado config.txt, dicho fichero es leído por la GPU antes de que el núcleo ARM sea inicializado. La configuración de este fichero permite modificar la frecuencia del procesador ARM, de la GPU, de la SDRAM,  suministrar más voltaje al núcleo de la Raspberry Pi,… .Por tanto se podría realizar “Overclocking” modificando el mismo. El contenido del fichero es:
# uncomment if you get no picture on HDMI for a default "safe" mode
#hdmi_safe=1
# uncomment this if your display has a black border of unused pixels visible
# and your display can output without overscan
disable_overscan=1
# uncomment the following to adjust overscan. Use positive numbers if console
# goes off screen, and negative if there is too much border
#overscan_left=16
#overscan_right=16
#overscan_top=16
#overscan_bottom=16
# uncomment to force a console size. By default it will be display's size minus
# overscan.
#framebuffer_width=1280
#framebuffer_height=720
# uncomment if hdmi display is not detected and composite is being output
#hdmi_force_hotplug=1
# uncomment to force a specific HDMI mode (this will force VGA)
#hdmi_group=1
#hdmi_mode=1
# uncomment to force a HDMI mode rather than DVI. This can make audio work in
# DMT (computer monitor) modes
#hdmi_drive=2
# uncomment to increase signal to HDMI, if you have interference, blanking, or
# no display
#config_hdmi_boost=4
# uncomment for composite PAL
#sdtv_mode=2
#uncomment to overclock the arm. 700 MHz is the default.
#arm_freq=800
# for more options see http://elinux.org/RPi_config.txt
Se ha instalado la herramienta hardinfo, que incorpora test a la CPU para ampliar la información obtenida hasta el momento.
Se ha generado un informe mediante la opción de Generate Report y la información que se ha considerado más útil, que amplía a la ya obtenida, es:
Memory 448MB (60MB used)
Audio Adapter
BRCM bcm2835 ALSbcm2835 ALSA - bcm2835 ALSA
MAPA EN MEMORIA
MODULO COMIENZO HEX FIN HEX COMIENZO DEC FIN DEC
SystemRAM 00000000 1bffffff 0 469762047
Kerneltext 00008000 004c0e77 32768 4984439
Kerneldata 004e2000 005b5127 5120000 5984551
bcm2708_vcio 20000000 20000fff 536870912[1] 536875007
bcm2708_systemtimer 20003000 20003fff 536883200 536887295
bcm2708_usb 20006000 20006fff 536895488 536899583
dwc_otg 20006000 20006fff 536895488 536899583
bcm2708_dma.0 20007000 20007fff 536899584 536903679
bcm2708_dma 20007000 20007fff 536899584 536903679
bcm2708_powerman.0 20100000 201000ff 537919488 537919743
bcm2708_gpio 20200000 20200fff 538968064 538972159
dev:f1 20201000 20201fff 538972160 538976255
uart-pl011 20201000 20201fff 538972160 538976255
bcm2708_spi.0 20204000 202040ff 538984448 538984703
bcm2708_i2c.0 20205000 202050ff 538988544 538988799
bcm2708_sdhci.0 20300000 203000ff 540016640 540016895
mmc0 20300000 203000ff 540016640 540016895
bcm2708_i2c.1 20804000 208040ff 545275904 545276159
bcm2708_usb 20980000 2099ffff 546832384 546963455
dwc_otg 20980000 2099ffff 546832384 546963455



[1] 536870912 = 512 MB RAM X 1024 KB/MB X 1024 B/KB
A través de la herramienta hardinfo también podemos testear la CPU, a través de diferentes pruebas. Puede ser un buen punto de partida comparar estos valores con los obtenidos cuando se realiza Overclocking sobre la CPU.
Otra herramienta que permite listar el hardware es lshw, que no viene instalada por defecto y la información que muestra no dista mucho de la vista hasta el momento, pero si indica que trabaja a 700MHz y el ancho de palabra es de 32 bit.

viernes, 7 de junio de 2013

LIBRERIA WIRING PI


WiringPi es una librería escrita en C y liberada baja licencia GNU LGPLv3, que puede ser empleada en varios lenguajes de programación, además de C y C++, con alguna pequeña modificación en forma de adaptación.
Su principal uso es en la programación de periféricos a través de los 26 pines de General Purpose Input Output (GPIO).
WiringPi, además, ofrece un comando que permite programar y configurar los pines de la GPIO, pudiendo efectuar la lectura y escritura de los pines desde la línea de comandos o incluso, incorporándola en un Shellscript.
Instalación utilizando GIT
Git es un software de control de versiones, libre y de código abierto, diseñado para manejar todo tipo de proyectos, desde pequeños a grandes con rapidez y eficiencia.
En caso de no estar instalado GIT se debería instalar. Para ello en primer lugar hay que actualizar los repositorios y posteriormente instalarlo.
sudo apt-get update sudo apt-get install git-core
Posteriormente hay que obtener la libreria mediante GIT
git clone git://git.drogon.net/wiringPi
Una vez descargado, hay que ir al directorio donde se encuentra y obtener una versión actualida.
cd wiringPi
git pull origin
A continuación, se debe ejecutar el script de creación e instalación en el directorio de WiringPi.
./build
El nuevo script se encarga de compilar y ejecutar todo, sin que sea necesaria la intervención del usuario. 
Descargando la librería.
Se va a proceder a descargar la aplicación en el directorio temporal /tmp.
cd /tmp
wget http://project-downloads.drogon.net/files/wiringPi.tgz
A continuación hay que desempaquetar el fichero.
tar xfz wiringPi.tgz
En este momento, se va a proceder a instalar las librerías relacionadas con wiringPi.
cd wiringPi/wiringPi
make
sudo make install
A continuación, se va a instalar la herramienta gpio, que permite en línea de comandos trabajar con los pines.
cd ../gpio make sudo make install
Finalmente, se van a instalar los ejemplos.
cd ../examples
make
Utilización
Para poder utilizar esta librería es necesario indicar que se va a emplear, en la primera parte del programa se incorpora la cabecera de la librería (#include<wiringPi.h ) y en la compilación se especifica que utilice la misma (gcc –o pruebas -l wiringPi pruebas.c).
Principales constantes y funciones de la librería
Funciones constructoras
Hay tres funciones constructoras que permiten trabajar con la librería Wiring Pi, todas ellas devuelven -1 en caso de que se produzca un error.
  • int wiringPiSetup(void) : Inicializa Wiring Pi y emplea el convenio de numeración de Wiring Pi.
A continuación se muestra la tabla resumen de los pines GPIO para la versión 1.
Ping wiringPi BCM GPIO Name Header Name BCM GPIO Ping wiringPi
3.3v 1 | 2 5v
8 R1:0/R2:2 SDA0 3 | 4 DNC
9 R1:1/R2:3 SCL0 5 | 6 0v
7 4 GPIO7 7 | 8 TxD 14 15
DNC 9 | 10 RxD 15 16
0 17 GPIO0 11 | 12 GPIO1 18 1
2 R1:21/R2:27 GPIO2 13 | 14 DNC
3 22 GPIO3 15 | 16 GPIO4 23 4
DNC 17 | 18 GPIO5 24 5
12 10 MOSI 19 | 20 DNC
13 9 MISO 21 | 22 GPIO6 25 6
14 11 SCLK 23 | 24 CE0 8 10
DNC 25 | 26 CE1 7 11
Para la revisión 2
Ping wiringPi BCM GPIO Name Header Name BCM GPIO Ping wiringPi
5v 1 | 2 3.3v
17 28 GPIO8 3 | 4 GPIO9 29 18
19 30 GPIO10 5 | 6 GPIO11 31 20
0v 7 | 8 0v
  • int wiringPiSetupGpio(void) : Idéntica a la anterior, pero utiliza la numeración de pines de Broadcom (BCM GPIO).
  • int wiringPiSetupSys(void) : En este caso utiliza la interfaz /sys/class/gpio, en vez de trabajar directamente sobre el Hardware.
Funciones generales
  • void pinMode(int pin, int mode) : Sirve para especificar el pin (primer argumento) y modo (segundo argumento), que puede ser entrada (INPUT), salida (OUTPUT) o salida PWM (PWM_OUTPUT).
  • void digitalWrite(int pin, int value) : Se utiliza para poner un pin, que previamente ha sido configurado como OUTPUT a dos posibles valores 1 (HIGH) o 0 (LOW).
  • void digitalWriteByte(int value) : Permite escribir en los 8 pines de la GPIO un valor.
  • void pwmWrite(int pin, int value) : Escribe el valor del registro PWM (segundo argumento) al pin indicado (primer argumento). El valor suministrado debe estar comprendido entre 0 y 1024, además, hay que tener en cuenta que sólo soporta PWM el pin BCM_GPIO 18.
  • int digitalRead(int pin) : devuelve el valor leído en el pin indicado (único argumento), que puede ser 1 (HIGH) o 0 (LOW).
  • void pullUpDnControl(int pin, int pud) : establece sobre el pin indicado (primer argumento) el modo de tensión o resistencia, elevar a 3v3 ( PUD_UP), tirar a tierra (PUD_DOWN) o ni elevar ni disminuir (PUD_OFF).
Funciones de control PWM
Las siglas PWM corresponden a pulse-width modulation, en castellano, Modulación por ancho de pulsos, consistente en cambiar el ciclo de una señal periódica. No se pueden utilizar cuando se trabaja en modo sistema (mode sys).
  • void pwmSetMode(int mode) : El generador puede trabajar en dos modos balanceado ( PWM_MODE_BAL ), que es el que utiliza por defecto Raspberry Pi o marca espacio (PWM_MODE_MS) .
  • void pwmSetRange(unsigned int range) : Establece el valor máximo del rango del registro PWM, establecido por defecto a 1024.
  • void pwmSetClock(int divisor) : Sirve para establecer el divisor del reloj PWM.
Funciones de tiempo
  • unsigned int millis(void) : Devuelve el numero de milisegundos que han transcurrido desde que se ha invocado a una función Wiring Pi.
  • void delay(unsigned int howLong) : Provoca la pausa del programa durante al menos howLong milisegundos.
  • void delayMicroseconds(unsigned int howLong) : Análogo al anterior, pero en este caso se estabecen microsegundos.
Program/Thread Priority
  • int piHiPri(int priority) : sirve para establecer la prioridad del programa o thread, que oscila entre 0 ,valor establecida por defecto y 99 valor máximo y permite la planificación en tiempo real. El valor devuelto es 0 en caso de éxito y -1 en caso de error. Sólo los programas ejecutados como root pueden cambiar su prioridad.
Funciones de interrupciones
  • int waitForInterrupt(int pin, int timeOut) : permite establecer un tiempo de espera en milisegundos (segundo argumento) para una interrupción definida sobre un pin ( primer argumento), en el caso de definir como timeOut -1 esperará indefinidamente. El valor devuelto es 0 en caso de éxito y -1 en caso de error. Esta función está obsoleta y se recomienda utilizar la que se presenta a continuación.
  • int wiringPiISR(int pin, int edgeType,  void (*function)(void)) : mediante esta function se puede establecer un manejador sobre un pin, además se debe especificar si se detecta mediante un flanco de bajada (INT_EDGE_FALLING) , un flanco de subida (INT_EDGE_RISING ), en ambos flancos (INT_EDGE_BOTH) o el pin no ha sido inicializado (INT_EDGE_SETUP). El valor devuelto es 0 en caso de éxito y -1 en caso de error.
Funciones de programación concurrente
Wiring Pi permite la utilización de hilos POSIX, así como mecanismos de exclusión mutua (mutex).
  • int piThreadCreate(void * (* fn) (void *) : Crea un Thread de una función que ha sido declarada previamente mediante PI_THREAD. La declaración sería similar a PI_TREAD(miThread){ código } y posteriormente, esta función será el argumento de la función. El valor devuelto es 0 en caso de éxito y -1 en caso de error.
  • void piLock(int keyNum) : bloquea una clave (keyNum) cuyo valor va de 0 a 3, cuando otro thread intenta bloquear a la clave, queda a la espera de que sea liberado.
  • void piUnlock(int keyNum) : Permite desbloquear una clave definida como en la función anterior.
Otras funciones
  • int piBoardRev(void) : indica la versión de la placa sobre la que se está trabajando.
  • int wpiPinToGpio(int wPiPin) : transforma el número de pin según el convenio de Wiring Pi al convenio de BCM GPIO.
  • void setPadDrive(int group, int value) : establece la “fuerza” de los drivers para un grupo de pins. 

jueves, 6 de junio de 2013

COMPILAR ENSAMBLADOR ARM Y C


En esta entrada se parte de unos conocimientos de programación básicos de ARM y C.
gcc
gcc (GNU Compiler Collection) es una colección de compiladores libres y a continuación se presentan sus principales argumentos:
  • -c Es utilizado para compilar o ensamblar los ficheros fuentes, pero sin enlazar.
  • -S Sirve para transformar un archivo que contiene un programa fuente en C en un archivo fuente en ensamblador.
  • -o archivo La salida del compilador se almacena en el archivo indicado.
  • -g Sirve para generar información de depuración, muy útil para poder utilizar posteriormente en programas de depuración.
  • -l librería Añade la libreria especificada en la compilación.
Para probar algunas opciones se va a partir del programa holamundo
#include<stdio.h>
main(){
printf("Hola Mundo\n");
}
Se va a compilar y ejecutar para ello
gcc -o holamundo holamundo.c
chmod +x holamundo
./holamundo
Si se desea generar el código en ensamblador
gcc -S holamundo.c
as
as (GNU Assembler) es un ensamblador del proyecto GNU, se van a citar aquellas que han sido más utilizadas.
  • -o archivo Sirve para que el archivo objeto generado se denomine archivo.
  • -g Sirve para generar información de depuración, muy útil para poder utilizar posteriormente en programas de depuración.
as –o holamundo.o holamundo.s
ld
ld (GNU Linker) sirve para enlazar ficheros objeto y generar un ejecutable.
  • -l librería Añade la librería especificada en la compilación.
  • -m maquina Especifica la arquitectura a emplear cuando se desensamblen ficheros objeto.
  • -dynamic-linker  Establece el enlazado dinámico
  • -T  Permite definir donde comienzan las secciones
  • -o archivo Sirve para que el archivo objeto generado se denomine archivo.
ld -dynamic-linker /lib/ld-linux.so.3 -o p1a p1a.o copy.o -T ldscript.ld
objdump
Es una herramienta que forma parte de las GNU Binutils, es una herramienta que muestra información sobre los programas objeto.
Se proceden a mostrar las entradas que se han considerado más relevantes del manual
  • -d /--disassemble Muestra los mnemónicos de ensamblador para las instrucciones máquina de fichobj. Esta opción sólo desensambla aquellas secciones para las que se espera que contengan instrucciones.
  • -D / --disassemble-all Como -d, pero desensambla los contenidos de todas las secciones, no sólo aquéllas donde se espera que contengan instrucciones.
  • ‐j / ‐‐section=   nombre Seleccionar información sólo de la sección mencionada.
  • -S Intercala código fuente con desensamblado.
  • ‐s / ‐‐full‐contents  Mostrar contenidos completos de todas las secciones.
  • -t Muestra las entradas de la tabla de símbolos.
Como ejemplo se va a partir del programa holamundo.c definido anteriormente, a continuación se procederá a compilar el archivo con las opciones –g para que genere información de depuración y –o para indicar un fichero de salida.
gcc –g –o holamundo holamundo.c
A modo de ejemplo se va a proceder a utilizar la opción –S (desensambla e intercala código fuente)
objdump –S holamundo
holamundo:     file format elf32-littlearm
Disassembly of section .init:

000082cc <_init>:
    82cc:       e92d4008        push    {r3, lr}
    82d0:       eb000020        bl      8358
    82d4:       e8bd8008        pop     {r3, pc}

Disassembly of section .plt:

000082d8 &lt;.plt&gt;:
    82d8:       e52de004        push    {lr}            ; (str lr, [sp, #-4]!)
    82dc:       e59fe004        ldr     lr, [pc, #4]    ; 82e8 <_init data-blogger-escaped-x1c="">
    82e0:       e08fe00e        add     lr, pc, lr
    82e4:       e5bef008        ldr     pc, [lr, #8]!
    82e8:       00008280        .word   0x00008280
    82ec:       e28fc600        add     ip, pc, #0
    82f0:       e28cca08        add     ip, ip, #32768  ; 0x8000
    82f4:       e5bcf280        ldr     pc, [ip, #640]! ; 0x280
    82f8:       e28fc600        add     ip, pc, #0
    82fc:       e28cca08        add     ip, ip, #32768  ; 0x8000
    8300:       e5bcf278        ldr     pc, [ip, #632]! ; 0x278
    8304:       e28fc600        add     ip, pc, #0
    8308:       e28cca08        add     ip, ip, #32768  ; 0x8000
    830c:       e5bcf270        ldr     pc, [ip, #624]! ; 0x270
    8310:       e28fc600        add     ip, pc, #0
    8314:       e28cca08        add     ip, ip, #32768  ; 0x8000
    8318:       e5bcf268        ldr     pc, [ip, #616]! ; 0x268

Disassembly of section .text:

0000831c <_start>:
    831c:       e3a0b000        mov     fp, #0
    8320:       e3a0e000        mov     lr, #0
    8324:       e49d1004        pop     {r1}            ; (ldr r1, [sp], #4)
    8328:       e1a0200d        mov     r2, sp
    832c:       e52d2004        push    {r2}            ; (str r2, [sp, #-4]!)
    8330:       e52d0004        push    {r0}            ; (str r0, [sp, #-4]!)
    8334:       e59fc010        ldr     ip, [pc, #16]   ; 834c <_start data-blogger-escaped-x30="">
    8338:       e52dc004        push    {ip}            ; (str ip, [sp, #-4]!)
    833c:       e59f000c        ldr     r0, [pc, #12]   ; 8350 <_start data-blogger-escaped-x34="">
    8340:       e59f300c        ldr     r3, [pc, #12]   ; 8354 <_start data-blogger-escaped-x38="">
    8344:       ebffffeb        bl      82f8 <_init data-blogger-escaped-x2c="">
    8348:       ebfffff0        bl      8310 <_init data-blogger-escaped-x44="">
    834c:       00008444        .word   0x00008444
    8350:       000083c8        .word   0x000083c8
    8354:       000083e4        .word   0x000083e4

00008358 :
    8358:       e59f3014        ldr     r3, [pc, #20]   ; 8374
    835c:       e59f2014        ldr     r2, [pc, #20]   ; 8378
    8360:       e08f3003        add     r3, pc, r3
    8364:       e7933002        ldr     r3, [r3, r2]
    8368:       e3530000        cmp     r3, #0
    836c:       012fff1e        bxeq    lr
    8370:       eaffffe3        b       8304 <_init data-blogger-escaped-x38="">
    8374:       00008200        .word   0x00008200
    8378:       0000001c        .word   0x0000001c

0000837c <__do_global_dtors_aux>:
    837c:       e59f3010        ldr     r3, [pc, #16]   ; 8394 <__do_global_dtors_aux data-blogger-escaped-x18="">
    8380:       e5d32000        ldrb    r2, [r3]
    8384:       e3520000        cmp     r2, #0
    8388:       03a02001        moveq   r2, #1
    838c:       05c32000        strbeq  r2, [r3]
    8390:       e12fff1e        bx      lr
    8394:       00010590        .word   0x00010590

00008398 :
    8398:       e59f0020        ldr     r0, [pc, #32]   ; 83c0
    839c:       e92d4008        push    {r3, lr}
    83a0:       e5903000        ldr     r3, [r0]
    83a4:       e3530000        cmp     r3, #0
    83a8:       08bd8008        popeq   {r3, pc}
    83ac:       e59f3010        ldr     r3, [pc, #16]   ; 83c4
    83b0:       e3530000        cmp     r3, #0
    83b4:       08bd8008        popeq   {r3, pc}
    83b8:       e12fff33        blx     r3
    83bc:       e8bd8008        pop     {r3, pc}
    83c0:       00010474        .word   0x00010474
    83c4:       00000000        .word   0x00000000

000083c8 :
#include
main(){
    83c8:       e92d4800        push    {fp, lr}
    83cc:       e28db004        add     fp, sp, #4
        printf("Hola Mundo\n");
    83d0:       e59f0008        ldr     r0, [pc, #8]    ; 83e0
    83d4:       ebffffc4        bl      82ec <_init data-blogger-escaped-x20="">
}
    83d8:       e1a00003        mov     r0, r3
    83dc:       e8bd8800        pop     {fp, pc}
    83e0:       00008454        .word   0x00008454

000083e4 <__libc_csu_init>:
    83e4:       e92d45f8        push    {r3, r4, r5, r6, r7, r8, sl, lr}
    83e8:       e1a06000        mov     r6, r0
    83ec:       e59f5048        ldr     r5, [pc, #72]   ; 843c <__libc_csu_init data-blogger-escaped-x58="">
    83f0:       e59fa048        ldr     sl, [pc, #72]   ; 8440 <__libc_csu_init data-blogger-escaped-x5c="">
    83f4:       e08f5005        add     r5, pc, r5
    83f8:       e08fa00a        add     sl, pc, sl
    83fc:       e065a00a        rsb     sl, r5, sl
    8400:       e1a07001        mov     r7, r1
    8404:       e1a08002        mov     r8, r2
    8408:       ebffffaf        bl      82cc <_init>
    840c:       e1b0a14a        asrs    sl, sl, #2
    8410:       08bd85f8        popeq   {r3, r4, r5, r6, r7, r8, sl, pc}
    8414:       e3a04000        mov     r4, #0
    8418:       e4953004        ldr     r3, [r5], #4
    841c:       e1a00006        mov     r0, r6
    8420:       e1a01007        mov     r1, r7
    8424:       e1a02008        mov     r2, r8
    8428:       e2844001        add     r4, r4, #1
    842c:       e12fff33        blx     r3
    8430:       e154000a        cmp     r4, sl
    8434:       1afffff7        bne     8418 <__libc_csu_init data-blogger-escaped-x34="">
    8438:       e8bd85f8        pop     {r3, r4, r5, r6, r7, r8, sl, pc}
    843c:       00008070        .word   0x00008070
    8440:       00008070        .word   0x00008070

00008444 <__libc_csu_fini>:
    8444:       e12fff1e        bx      lr

Disassembly of section .fini:

00008448 <_fini>:
    8448:       e92d4008        push    {r3, lr}
    844c:       e8bd8008        pop     {r3, pc}

Muestra los símbolos con los que enlaza un programa.
nm holamundo
00010478 d _DYNAMIC
00010568 d _GLOBAL_OFFSET_TABLE_
00008450 R _IO_stdin_used
         w _Jv_RegisterClasses
00008468 r __FRAME_END__
00010474 d __JCR_END__
00010474 d __JCR_LIST__
00010594 A __bss_end__
00010590 A __bss_start
00010590 A __bss_start__
00010588 D __data_start
0000837c t __do_global_dtors_aux
00010470 t __do_global_dtors_aux_fini_array_entry
0001058c D __dso_handle
00010594 A __end__
0001046c t __frame_dummy_init_array_entry
         w __gmon_start__
00010470 t __init_array_end
0001046c t __init_array_start
00008444 T __libc_csu_fini
000083e4 T __libc_csu_init
         U __libc_start_main@@GLIBC_2.4
00010594 A _bss_end__
00010590 A _edata
00010594 A _end
00008448 T _fini
000082cc T _init
0000831c T _start
         U abort@@GLIBC_2.4
00008358 t call_gmon_start
00010590 b completed.5637
00010588 W data_start
00008398 t frame_dummy
000083c8 T main
         U puts@@GLIBC_2.4
C y ARM
A continuación se va a mostrar el siguiente ejemplo, la función en ensamblador es una suma almacenada en suma.s y es llamada desde el programa main.c.
main.c
#include<stdio.h>
extern int suma(int a, int b);
int main(int argc, char *argv[])
{
  printf("== sum ==\n");
  int a = 71;
  int b = 29;
  printf("%d + %d = %d\n", a, b, suma(a, b));
  return 0;
}
suma.s
  .align 2
  .arm
  .global suma
suma:
  add     r2, r0, r1 in r2
  mov             r0, r2                    
  mov             pc, lr            
Pasos para tener este programa como ejecutable
gcc -c main.c
as -o suma.o suma.s
gcc -o main suma.o main.o
chmod a+x suma
./suma
ARM y C
En el siguiente ejemplo partimos de un fichero copy.c que copia de una cadena origen a una cadena destino n carácteres.
void __c_copy(char *orig, char *dest, int tam)  {
 int i;
 for(i=0;i<tam;i++){

           dest[i]=orig[i];
    }
}
El siguiente programa en ensamblador contenido en el fichero main.s emplea la función anterior para copiar una cadena y mostrarla por pantalla.
.text
.global _start
_start:
       .extern __c_copy
       ldr r0, =.orig
       ldr r1, =.dest
       mov r2, #11
       bl    __c_copy
       ldr r0, =.dest
       bl _imprime
bl exit
.global _imprime
       _imprime:
             stmdb sp!, {r0,r1,lr}
             mov r1,r0
             ldr r0, =.string
             bl printf
             ldmia sp!, {r0,r1,pc}
.data
.string:
.asciz "%s\n"
.orig:
.asciz "Hola Mundo"
.dest:
.space 11
.end
Pasos para tener este programa como ejecutable
gcc -c copy.c
as -o main.o main.s
ld -dynamic-linker /lib/ld-linux.so.3 -lc -o main main.o copy.o
chmod a+x main 
./main