Panel de Control (Parte 5): Firmware

mayo 24, 2018 circuiteando 0 Comments

Para el desarrollo del firmware no tenía claro que herramientas y/o librerías iba ha utilizar, por lo que decidí probar las más conocidas y/o recomendadas en los foros para micros de ST, dejando a un lado el IDE propio de ST, SystemWorkbench, que utilicé durante las pruebas iniciales. Ahora buscaba un entorno que me permitiera ahorrar tiempo, poder desarrollar el firmware con más rapidez y menos complicaciones y configuraciones.

El primer candidato fue Mbed, un framework con un editor online.

Mbed (Compilador online)

Intenta ser algo parecido al entorno Arduino, pero con el IDE en la nube. Nos conectamos a una página web y tras registrar la placa Nucleo podemos programar en C++ y buscar librerías propias de Mbed o subidas por la comunidad. Aunque no se puede comparar con la cantidad de usuarios y librerías de Arduino.

No a gusto con eso de tener que tener conexión a internet para poder programar, me encontré con PlatformIO, una herramienta que permite instalar y administrar diferentes frameworks. Se integra muy bien con el editor Atom.

PlatformIO en Atom

Permite programar un montón de placas de diferentes fabricantes con el mismo entorno de desarrollo, y dispone de un repositorio de librerías que realiza la comunidad donde se puede buscar e instalar directamente desde la consola de comandos (todo de forma local). Por lo instalé Mbed de forma local mediante esta herramienta.

Me gustó el hecho de que Mbed dispone de funciones antirebotes para los interruptores/pulsadores mecánicos incluidas en el framework.

Hasta ahora, las rutinas antirebotes las realizaba por software para unos cuantos pulsadores/interruptores. Esto quiere decir, que por cada pulsador/interruptor el micro tenía que esperar cierta cantidad de tiempo (normalmente entre 10 y 20 ms) para determinar si el cambio de estado era o no producido por un rebote.

Si el panel dispone de aproximadamente unos 100 conmutadores, si se comprobara de forma secuencial uno tras otro, más los rotatorios, que al realizar una lectura analógica se asegura su estado haciendo una media de 10 lecturas, tardaría demasiado tiempo en realizar las lecturas y habría un retardo apreciable para la persona que activa el interruptor. Pero en caso de ser un pulsador, si se pulsa y suelta en menos tiempo de lo que tarda la rutina en leer los pulsadores, no se detectaría el cambio. Por lo que pongo dos requisitos: que se detecte una pulsación de al menos 20ms para los pulsadores y de 100ms para los rotatorios (10 lecturas por 10ms por lectura).
También hay que tener en cuenta la comunicación con el ordenador y las otras placas. Se tendría que comprobar cada cierto tiempo si hay un mensaje pendiente o no en los buffers de lectura.

Con todo lo dicho anteriormente, pienso que intentar hacerlo todo en un solo bucle sería complicado. Las rutinas tendrían que ser cortas e intercaladas para afectar lo menos posible con los tiempos de lectura de los conmutadores, al final se trata de que no se aprecie lag entre la pulsación de un botón y su respuesta en el ordenador.

Esto me lleva ha probar un RTOS, nunca antes los había utilizado, pero me pareció útil. Si tiene un sistema operativo y emula el paralelismo mediante hilos de ejecución a los que asigna tiempo del procesador, igual que el PC, podría simplificar las cosas y asignar las tareas a diferentes hilos. Por ejemplo, uno encargado de comprobar los pulsadores, otro para los rotatorios, otro para las comunicaciones, etc... Por los que pasé a probar MbedOS.

Siendo un completo novato en esto de los RTOS, me di de frente con varios problemas, no saber que se está ejecutando en cada momento, puesto que si se queda bloqueado se necesita saber que hilo lo ha originado. También surgen problemas con el acceso a un recurso o variable desde varios hilos, partes a las que se puede acceder o no, dependiendo si se está dentro de una rutina de interrupción (ISR).

Todo estos problemas son nuevos para los que venimos de la programación en un solo bucle, sobre todo de los micros de 8 bits, donde no se suele utilizar un RTOS.

Hay que decir que muchos problemas no causan el bloqueo del micro, sino la corrupción de datos, lo que lleva a problemas que se manifiestan de forma aleatoria. Nada deseable en absoluto.
Por lo que tras quedarme atascado varios días, decidí cambiar nuevamente, ésta vez a un RTOS que permita hacer "debuggin".

Esto del "debuggin" por software o hardware es algo que no está implementado en Mbed o en Arduino. Las única herramienta que se suele utilizar es el famoso print, e ir así mostrando el valor de variables en ciertas partes del firmware para averiguar el comportamiento del programa. Todo ello por el puerto serie del micro.

Al final me encontré con ChibiOS, un RTOS que incorpora ambas formas de "debuggin". Por hardware, es capaz de pausar la ejecución en el micro y ver el valor de las variables que queramos, el valor que hay en los registros, el estado de los pines, etc... ¡una maravilla!. Y esto no acaba aquí, si no que mediante software incluido en el núcleo de ChibiOS, también podemos ver los hilos totales que hay, junto con su estado, tiempo de ejecución, estadísticas, pila de llamadas, etc...

También se realizan comprobaciones de la pila, y de ciertos errores que se suelen cometer, como llamar a una función dentro de una rutina de interrupción, y está función no estar preparada para trabajar desde la interrupción. Lo que origina la parada inmediata del micro y se informa del error encontrado. ¡Esto era lo que me traía de cabeza! y era incapaz de verlo.

La documentación es de las mejores que existen y en cada función se indica si es o no válida para llamarse desde dentro de una rutina de interrupción, si es segura para llamarse entre varios hilos (thread safe) y muchas cosas más.

También se puede elegir entre utilizar las funciones de RTOS o realizarlo todo en un único bucle (hilo), aparte de que incorpora sus propias librerías de acceso al hardware (HAL), que se pueden utilizar de forma independiente del kernel RTOS.

Y para rematar, se distribuye todo empaquetado junto con un IDE basado en Eclipse: ChibiStudio.

ChibiStudio

El firmware final

La versión final del firmware de los micros ST ARM Cortex-M se ha realizado en el IDE de ChibiOS, ChibiStudio y sus características son las siguientes:

  • Rutinas antirrebote de pulsadores/interruptores ( en 1 hilo).
  • Lectura analógica de rotatorios y mini joystick realizada por hardware. (Realiza 10 medidas consecutivas del ADC y las almacena en la memoria mediante un solo comando por hardware. En 1 hilo)
  • Lectura de encoders con 96 pasos por interrupciones y en 1 hilo de ejecución diferente.
  • Lectura del puerto serie por interrupciones y en 1 hilo diferente. Comunicación con corrección de errores mediante CRC16. Cada vez que se manda un comando a una placa o PC, se comprueba que los datos son correctos, de no ser así se envía un comando para que se vuelvan a enviar nuevamente).
  • Protección contra desbordamiento de la pila. En caso de detectarse, se bloquea el micro.
  • Watchdog. De mantenerse el micro bloqueado por 2 segundos aproximadamente, se produce un reinicio del mismo.
  • Uso de "mutex" para evitar que 2 hilos adquieran un mismo recurso de forma simultánea.
  • El propio comando que se envía al activar cualquier control, incluye información del micro, puerto, pin y estado del mismo que originó la llamada, en formato hexadecimal.
  • Puesta del micro en modo "sleep" (ahorro de energía) cuando no realiza ninguna tarea. (En ChibiOS existe siempre un hilo llamado Idle, que se ejecuta cuando no hay ningún otro que reclame tiempo de ejecución. Este hilo se encarga de poner el micro en modo "sleep").
El firmware de las placas son variantes del principal adecuándolo a las tareas que realiza. (No tienen encoders ni rotatorios conectados a ellas).

Por último, se ha utilizado un micro Atmega 16u2 que llevan las placas Arduino Uno R3 para convertir los comandos pasados por el puerto serie en informes USB HID para la comunicación con el PC. Dado que los drivers que emulan un puerto serie daban problemas y fallaba la comunicación al cabo de una hora o hora y media.

Un dispositivo USB HID que manda los datos en crudo (RAW) como es el caso del panel, no necesita drivers.

Para el firmware del protocolo USB se ha utilizado la librería LUFA. Muy recomendada, y con posibilidad de utilizar muchos de los modos en los que un dispositivo USB se puede configurar, incluyendo ejemplos de los mismos.

Cabe destacar que se ha utilizado un analizador lógico a la hora de comprobar el funcionamiento del sistema CRC y poder ver la trama que se estaba transmitiendo en cada caso. Imprescindible para localizar problemas en las tramas de comunicación.

Puntas de prueba del analizador lógico conectadas al bus de datos (SPI)
Error: el dispositivo esclavo no responde.
Prueba de corrección de errores en los puertos serie.

El dispositivo recibe un comando con un byte de más (0xFF), se reconoce el error y se manda por TX una petición de reenvío, después se recibe el comando nuevamente, esta vez correctamente.

Petición de reenvío

Se comprueba que se transmite la petición de reenvío mientras se reciba un comando erróneo.

Propagación por uart

Se observa como el comando recibido por un puerto serie, se transmite por otro diferente hacia otra placa.

Los 5 firmwares se pueden descargar desde el repositorio.

En el próximo artículo se hablará del programa de PC que recibe los datos del panel.

0 comentarios: