2019/07/29

Germinómetro con sAPI del firmware v3

Necesitaba medir humedad y temperatura para un trabajo práctico escolar y recordé que puedo hacerme un sensor, qué loco, ¿no?




Busqué la edu-ciaa-nxp, el dht-11 y el poncho educativo por el display lcd, me bajé el Firmware V3 que Eric muy recientemente ha publicado y adelante:

git clone https://github.com/ciaa/firmware_v3.git

Temperatura y humedad



Ando medio raro, leí las instrucciones ANTES de fallar.

Tambien un poco vago, llamé

make board_select board_program


Eligiendo la placa y el path, examples/c/sapi/dht11_temp_humidity, para que me cree board.mk

Hice el export para que encuentre el compilador y lo de siempre...


export PATH=$PATH:....

make

make download

miniterm.py /dev/ttyUSB0 115200

Y anda.


Display


Parecido, la ruta es examples/c/sapi/lcd/gpio y no hace falta redefinir la placa y no sólo anda, sino que ya dice "Temp y Hum", parece que la estación meteorológica es el nuevo blinky.

Integración


Tomé el medidor, aunque pudo haber sido el del lcd y le transferí lo que necesitaba del lcd, que era la inicialización, el caracter de grados y lcdGoToXY(), lcdSendStringRaw(), etc. Metí las mediciones con un sprintf() en los buffers de entrada de lcdSendStringRaw() y listo, anda.

Finalmente lo saqué todo a mi repo y en el repo del firmware_v3 puse un symlink al mío, seleccioné el programa y lo habitual:

mkdir projects
cd projects
ln -s ../../../cpantel/Germinometro
cd ..
make select_program
make clean && make && make download

No, no tan fácil, a make select_program no le gustó el symlink:

Error: this script only work with paths inside repository folder.
If you want to use a path outside repository folder please change program.mk manualy.


Y como me había llevado sólo una hora llegar hasta acá, moví el proyecto a la carpeta al lado de los ejemplos y listo.



El sistema completo


Ya me supera un poco poner una tarjeta SD para registrar las mediciones y ponerle una pila, ponerlo en hora, así que le conecté una netbook y por puerto serial, que ya me lo había dado el primer ejemplo, las mando a un txt con un timestamp


miniterm.py /dev/ttyUSB2 115200 \
| while read LINE; do \
  TS=$(date "+%Y-%m-%d %H:%M:%S");\
  echo $TS $LINE; \
done \
| tee --append log.txt

Le pido a miniterm.py o tu programa favorito tal que puedas colgarte de su STDOUT que lea cada linea, le antepongo un timestamp y lo tiro a la pantalla y a un archivo en modo concatenación.

El código en github.

Nota de color


Me confundí al comienzo y me estaba compilando el ejemplo por default, que muestra "LED apagado" en el serial.

Para diagnosticar mis amigos fueron
  • buscar strings en el ejecutable para comprobar que se estuviera grabando
  • git grep con el texto de lo que estaba viendo en el serial
  • borrar .gitignore para ver que está tocando el proceso de compilación, lo recuperás con:

    git checkout .gitignore

2019/07/26

Como entender y lidiar con XDC files en Vivado 2018.2

En esta entrada relato el camino un tanto sinuoso de comprensión de que es un archivo XDC que he seguido.

Siguiendo los tutoriales de Vivado, que son muy claros, llegué a la parte de los constraints, los archivos XDC que dicen como se van a conectar las patitas del FPGA con los periféricos de la placa que tengas, en mi caso Nexys-4 DDR. Si, en la página dice "retired". Entre que la pedí y llegó, eso pasó.

Previamente, había comenzado con información específica de la placa que tengo, de seguir vos este camino con otra placa, tendrías que adaptarte.

En el paso 6 del tutorial dice de bajarte el zip de constraints, pero preferí pegarle al repo:

git clone https://github.com/Digilent/digilent-xdc

Este es el momento en que uno debería leer la documentación para comprender que es un XDC, pero como siempre elegí arrojarme contra los archivos a ver que se puede comprender y dejar el manual para más tarde, esto es lo que hice y me funcionó bastante bien, me las puede arreglar con la adaptación de proyectos ISE a Vivado, lo que implica algo de uso de los XDC pues hay que recrearlos a partir de los UCF y de las interfaces del top module. Esto lo mostraré en Para estudiar Programming FPGAs: Getting Started with Verilog, cuando termine.


Volviendo, hay varios proyectos de ejempo y de ahí obtuve los links a los demos y en cada uno a los repos:

Los cloné:

git clone https://github.com/Digilent/Nexys-4-DDR-GPIO.git
git clone https://github.com/Digilent/Nexys-4-DDR-Keyboard.git
git clone https://github.com/Digilent/Nexys-4-DDR-OOB
git clone https://github.com/Digilent/Nexys-4-DDR-XADC.git


Busqué los XDC:

find Nexys-4-DDR-* -iname "*xdc"

Nexys-4-DDR-GPIO/src/constraints/Nexys4DDR_Master.xdc
Nexys-4-DDR-Keyboard/src/constraints/Nexys4DDR_Master.xdc
Nexys-4-DDR-OOB/src/constraints/Nexys4DDR_C.xdc
Nexys-4-DDR-XADC/src/constraints/Nexys4DDR_Master.xdc


Y a jugar con kdiff3 o tu herramienta de comparación preferida.

A mi me gusta esta:

kdiff3 Nexys-4-DDR-GPIO/src/constraints/Nexys4DDR_Master.xdc \
       Nexys-4-DDR-XADC/src/constraints/Nexys4DDR_Master.xdc \
       Nexys-4-DDR-Keyboard/src/constraints/Nexys4DDR_Master.xdc

Comparé entonces entre los cuatro proyectos y contra digilent-xdc y pensé que por algún perverso motivo, en los get_ports los nombres cambian. Luego encontré que responde a un motivo muy sencillo: son los nombres que se le dan en los módulos a los pines, pueden venir de un diseño genérico, de otra placa, no hay manera que esos nombres sean los mismos en distintos proyectos.

Esto es el proyecto de GPIO vs el XDC virgen, en los botones cambian los nombres y en los pines de los 7 segmentos, además cambia el tipo.




Lo que dice luego es que más allá de des/comentar no es recomendado cambiar nada al menos del clock.

El proyecto más interesante es el OOB, pues toca casi todos los periféricos.



Dejando un poco de lado la exploración, que a mi me gusta y sirve pues es divertida y me hace hallar muchas preguntas que luego la documentación me responde, he aquí lo que he aprendido en la documentación:

En una CPU y cualquier integrado "común", los pines tienen funcionalidad fijas: uno es clock(), otro es IO y así.

 
By Bill Bertram - Own work, CC BY 2.5, https://commons.wikimedia.org/w/index.php?curid=473063


En un microcontrolador, que contiene un CPU y periféricos, cada pin tiene una o más posibles funcionalidades y un mecanismo para configurar cual de ellas es elegida. Los pines configurables, permiten entonces conectarse internamente a ciertos periféricos internos para exponer su funcionalidad al exterior del chip

En esta imagen sacada del documento elaborado por Eric Pernia que también aportó el párrafo anterior y la siguiente enumeración (gracias Eric), se pueden apreciar las funciones:
  • Nombre del pin de la serigrafía o donde está conectado (ej. LCD1 es un nombre de pin de la serigrafía, es horrible la serigrafía de la EDU-CIAA-NXP, confunde más de lo que ayuda).
  • Número de pin del microcontrolador (ej. 9).
  • Nombre del pin que le da el fabricante (ej. P4_4).
  • Función 0 (ej. GPIO2[4]).
  • Función 1 (ej. CTOUT_2).
  • Función 2 (ej. LCD_VD1).
  • Función 3 (ej. Reserved). Función 4 (ej. Reserved).
  • Función 5 (ej. LCD_VD20). Función 6 (ej. U3_DIR).
  • Función 7 (ej. SGPIO10).
  • ANALOG_SEL (ej. DAC).



El resto de los diagramas del proyecto CIAA están aquí.


Una FPGA puede mapear casi cualquier cosa que tenga adentro a casi cualquier pin y digo "casi" por las dudas para no decir "todo".


Pero, la FPGA está físicamente soldada a una placa entonces sus pines ya están fijados a ciertos cirtuitos electrónicos físicos inamovibles. Eso nos regresa a la situación de la CPU con respecto a algunos pines. Otros son como los de un microcontralador.

El XDC tiene entonces ese mapeo y lo provée el fabricante de la placa.

A fines prácticos:

set_property -dict { PACKAGE_PIN H17 IOSTANDARD LVCMOS33 } [get_ports { running_led }]; 

#IO_L18P_T2_A24_15 Sch=led[0]

PACKAGE_PIN: dice cuál pin físico es, no habría que tocar.

IOSTANDARD: tiene que ver con características electrónicas, setea a LVCMOS33, que es GPIO.

Para el pmod JXADC tiene IOSTANDARD LVDS, entiendo son entradas analógicas.

get_ports: dice como se va a llamar y es lo único que los básicos como yo podemos modificar.


El comentario es útil dejarlo para saber cual era el nombre original.

En Zynq, que es un chip con un microcontrolador y una FPGA, mmh, ahí la cosa se debe complicar, cuando llegue agregaré acá o en otra entrada.

Tambien quedará para el futuro el clock:

set_property -dict { PACKAGE_PIN E3    IOSTANDARD LVCMOS33 } [get_ports { CLK }];
                                                                          #IO_L12P_T1_MRCC_35 Sch=clk100mhz
create_clock -add -name sys_clk_pin -period 10.00 -waveform {0 5} [get_ports { CLK }];



A fines más prácticos, el modo de usarlo que he destilado es:

  • Tener el archivo, por ejemplo en mi caso Nexys-4-DDR-Master.xdc en algún lugar accesible, con permisos 644.
  • Crear el proyecto
  • Copiarlo y cambiarle los permisos a 664.
  • Ajustar
¿Por qué el asuntito de los permisos? Por que si al agregarlo al proyecto desde Vivado te equivocás y no le ponés "copiar", te puede quedar referenciado a tu archivo común y cuando lo modifiques rompes los otros proyectos que puedan tener el mismo defecto. Le pasó a un amigo y yo te cuento.