Programando sistemas embebidos I variables

Desarrollar código para sistemas embebidos no es lo mismo que programar aplicaciones para PC. Los sistemas embebidos basados en uno o más micros (no entramos en sistemas con DSPs, FPGAs o mixtos) pueden funcionar tanto con:

  • Sistema operativo embebido como por ejemplo Linux Embedded o Windows CE que permiten una programación a más alto nivel en C y C++ en el caso de Linux y también en C# en el caso de Windows.
  • Sistema operativo de tiempo real (RTOS) como son embOS o el ahora tan de moda FreeRTOS que es compatible y ya tiene versiones para micros tan populares, sencillos y económicos como los Cortex-Mx de ST (familia STM32), los PIC24 y PIC32 de Microchip o los MSP430 de Texas Instruments.
  • Firmware desarrollado directamente en C o C++ sin ningún tipo de de sistema operativo embebido o RTOS.

A estas alturas, el desarrollo de código para sistemas operativos embebidos es muy parecido al desarrollo de aplicaciones para PCs, el entorno de trabajo compilando con el gcc para la arquitectura de nuestro micro en el caso de Linux, Visual Studio para el caso de Windows. Aunque es muy importante ser consciente de las limitaciones del sistema embebido que a diferencia de un PC, son recursos como la RAM o el espacio destinado al sistema de ficheros que en muchos casos será una memoria Flash o bien una tarjeta de memoria tipo SD.

Estas limitaciones, así como la “potencia” del micro deben afectar positivamente a nuestro desarrollo de código pues seremos más conscientes de los recursos con los que contamos y en consecuencia haremos un código más eficiente. Aún así, esta eficiencia y simplicidad del código debe ser siempre lo mejor posible tanto para sistemas embebidos como para aplicativos de PC aunque si bien es verdad que en desarrollos de software para PC podemos permitirnos alguna licencia más o un código no optimo no afectará tan negativamente como lo haría en el caso de los sistemas embebidos.

La problemática que debe afrontar el programador al encarar la programación del proyecto no será únicamente la optimización del código ajustándose a los recursos sino que como tal, el sistema embebido tiene algunos condicionantes como la configuración correcta del hardware y periféricos específicos, la eficiencia en cuanto a consumo (un buen desarrollo firmware puede afectar positivamente más de lo que uno a priori puede intuir), la estabilidad pues los sistemas embebidos no son aplicaciones de PC encaradas a un usuario que pueden ser reseteadas en caso de mal funcionamiento y que las comunicaciones no afecten al rendimiento del sistema, pues los sistemas embebidos son módulos o partes hardware que forman parte de otro sistema mayor y en gran medida intercambian información con otros subsistemas.

Al principio de este post apuntaba tres posibilidades a la hora de enfocar el desarrollo de sistemas embebidos: sistemas operativos embebidos, RTOs y firmware utilizando el compilador C o C++ facilitado directamente por el fabricante del microcontrolador. Es en el tercer caso, el desarrollo de firmware, donde todos los factores críticos descritos (recursos, eficiencia,  simplicidad, robustez, …) son mucho más sensibles a la calidad del programador pues no tenemos ninguna capa por debajo que nos ayude a gestionar memoria o nos aporte soluciones no críticas en caso de fallo del programa.

Aunque queda pendiente colgar cuales son los criterios para saber como haremos funcionar nuestro embebido a nivel de firmware (Emb.OS, RTO o Firmware), a continuación he hecho una pequeña compilación de consejos en base a conocimientos y experiencia propios y una pequeña compilación de pruebas realizadas por terceros. En este post encontraréis los consejos relacionados con la definición de las variables, en este otro post: Programando sistemas embebidos II tratamiento.

¿variables signed o unsigned?

Pues la respuesta a esta pregunta es muy sencilla, sino se van a usar valores negativos, sin ningún tipo de duda usar variables tipo unsigned como son los unsigned int (16bits – 2bytes), los unsigned char (8bits – 1byte) o los unsigned long (32bits – 4bytes). Esta es una afirmación que comparten todos los programadores de sistemas embebidos ya funcionen con o sin sistema operativo. Esto se debe a la simple cuestión que la gran mayoría de compiladores condicionan las operaciones sobre estas variables dependiendo de si son variables con o sin signo, pues en el caso de operaciones como la división o la multiplicación se obtiene un mejor rendimiento en el caso de las variables unsigned que en el caso de las signed que nos ocupan más ciclos de instrucción (pensad en como harías estas operaciones en ASM). Para un par de variables seguramente no afecte significativamente, pero si por costumbre tenemos todas las variables como char, int o long acabará repercutiendo seguro, imaginad que tenemos que parsear y realizar cálculos sobre un array y no podemos hacerlo de forma “asíncrona” pues debemos hacerlo todo de golpe.

tamaño de las variables

En cuanto al tamaño de las variables deberíamos adaptarnos lo máximo posible al bus de datos nativo del micro que se esté usando y como en el caso anterior independientemente de si trabajamos con o sin sistema operativo embebido. Por poner algunos ejemplos, si trabajamos con un procesador de 8bits como los RISC de Microchip (familias 16F y 18F) debemos evitar, en medida de lo posible (esta frase me recuerda al código de circulación), variables de más de 8 bits por lo que es preferible variables tipo unsigned char o char. En el caso de trabajar con micros de 32bit como Cortex-Mx de ST Microelectronics (SMT32) lo recomendable serían los unsigned long. Igualmente es importante estar bien documentado sobre el microprocesador que se utiliza pues existen procesadores que incorporan bloques específicos para tratar con las variables más pequeñas o mayores que aplican desplazamiento o máscaras mientras que otros tienen pipeline específico para estos unsigned int, unsigned char de un tamaño inferior al nativo del bus de datos. En cualquier caso no hay que tomarse este consejo como un NO rotundo, pues es evidente que si debemos trabajar con valores más grandes a los posiblemente representados por una variable del tamaño nativo del micro lo hacemos pero optimizamos los cálculos en los que se vea implicada dicha variable. Es como en el caso de tratar con variables con coma flotante cuando no tenemos un bloque del micro dedicado al cálculo de estas variables, si queremos aplicar varios coeficientes procuraremos unificarlos en uno solo para realizar el cálculo una única vez.

dónde declaro las variables

Cuando nos enseñan a programar siempre nos dicen: “en una función primero la declaración de variables y después el tratamiento”. Pues bien, muchos programadores dedicados al desarrollo de software para sistemas embebidos con sistema operativo afirman lo siguiente: “Declarar variables sólo cuando realmente se necesitan y no al inicio de la función que se está programando. Este hecho permitirá que el compilador utilice mejor los registros internos y evitar así la asignación de un registro a una variable que se utiliza sólo más tarde.” Me parece una afirmación más que razonable pero también es cierto que esto no lo permiten todos los compiladores, sobre todo cuando se trata de atacar directamente en C la programación del micro. En este segundo caso, independientemente de si el compilador lo permite o no, al no tener un sistema operativo que ayude a la gestión de memoria quizás vale la pena conocer como trata estas variables el compilador que se utilice. Es posible que la diferencia entre una declaración al inicio de la función no produzca mejora alguna.

También es verdad que para el mantenimiento del código el hecho de declarar variables en medio del código lo hace menos sostenible pues para el  posible heredero del desarrollo, las variables declaradas de esta forma pueden suponerle un dolor de cabeza y pueden dificultar su comprensión si el código es algo complejo. En este caso la documentación y el seguimiento de una hoja de estilo DEBERÍAN ser más aclaradoras de lo que ya DEBEN serlo por defecto (Está en mayúsculas porque es algo que parece que por las prisas o pereza normalmente no se hace…).

 

Tagged with: , , , , , , ,
Posted in Blog Técnico, Hardware Firmware, Sistemas Embebidos
3 Comments » for Programando sistemas embebidos I variables
  1. Zunett dice:

    Hola , yo estudio esta carrera en el campus Monterrey y en mi opinión una de las carreras que tendrá mas futuro en México , asi como una de las mejores que tiene el Tec de Monterrey , voy en 2 semestre y ahora me apasiona más es muy buena carrera .La carrera es muy interesante y aunque es un poco difícil vale la pena.Me gustaría que hubiera más impulso en esta carrera ya que en los paises desarrollados (USA , europa) las telecomunicaciones juegan un papel muy importante en la economia del país . ojala los empresarios se fijen en esta carrera ya que en el tec tenemos visión de no solo trascender, si no destacar como personas en nuestra rama.

  2. Gain dice:

    Gracias, una buena información. ;)

  3. Asterio dice:

    Saludos.
    Me dedico al diseño de circuitos con microcontroladores y la informacion expuesta me parece muy interesante, comparto algunas opiniones al respecto. Tomaré en cuenta los consejos.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos necesarios están marcados *

*


*

Puedes usar las siguientes etiquetas y atributos HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

enlaces patrocinados