ExOS – Sistema Operativo Posix Integrado
El sistema operativo de próxima generación para el mundo de los microcontroladores que permite pasar de un prototipo de hardware a una solución comercial en poco tiempo.
Introducción
Tanto mi equipo como yo llevamos más de 20 años trabajando como desarrolladores de nuestro propio hardware, así como de hardware de terceros.
Comenzamos, como la mayoría de los equipos de desarrollo, con innumerables ideas y el mayor entusiasmo posible. Sin embargo, durante el proceso de desarrollo, encontramos varios de esos problemas típicos que cualquier empresa dedicada al desarrollo de electrónica encuentra hoy en día, como por ejemplo: los problemas que surgen cuando se llega al paso de convertir una idea en un prototipo, y cómo, al mismo tiempo, este prototipo necesita convertirse en una solución comercial viable. ¡Una tarea arduamente complicada!
Ese paso o transición tiende a ser extremadamente importante, ya que definirá cómo será el prototipo final en circunstancias normales. Pero, llegar a este punto implica tomar decisiones que siempre son difíciles y generalmente están llenas de problemas e inconvenientes.
Cuando no se tiene experiencia en electrónica, es común elegir aquellas plataformas cuya curva de aprendizaje parece ser más rápida. El problema de esta opción reside en que, suponiendo que se necesite más potencia o simplemente cambiar el micro para mejorar los costos de la solución final, por ejemplo, no sería posible, ya que la simplicidad de programación generalmente va asociada a desventajas porque permite exclusivamente el uso de esa plataforma. Estas plataformas a menudo tienen entornos de desarrollo personalizados y usan sus propias bibliotecas de código exclusivas, restringiendo o incluso haciendo imposible cambiar a una plataforma diferente, dado el caso.
Por el contrario, cuando se trata de programadores experimentados, lo habitual es programar el micro tú mismo o usar algún kernel específico para microcontroladores. Esta opción no está exenta de problemas ya que, en general, cambiar de plataformas puede ser bastante difícil por sí mismo, a menos que alguno de los sistemas operativos elegidos soporte esa plataforma. En cualquier caso, y aunque esta opción pueda ser mejor que la anterior, específicamente en cuanto al cambio de plataformas, y dado que normalmente muchos de ellos soportan la mayoría de los micros del mercado, su limitación se define cuando te ves obligado a programar de una manera muy particular, tal y como se ha establecido para el kernel seleccionado, ya que no existe un estándar. Si las circunstancias demandaran un cambio entre dos kernels, aprender a programar el nuevo sería inevitable, lo que invalidaría gran parte del código y las lógicas de programación utilizadas anteriormente.
Anteriormente, la mayoría de los productos de hardware eran lo que conocemos como ‘independientes’, es decir, que no se comunicaban con otros elementos, o, si lo hacían, era a través de protocolos simples como RS232, RS485, etc.
Hoy en día, la mayoría de los dispositivos desarrollados pueden comunicarse con teléfonos inteligentes o computadoras a través de protocolos de alto nivel como USB, Wi-Fi, Bluetooth, etc., de modo que la configuración y el acceso operativo se pueden realizar fácilmente a través de ellos. De hecho, el uso de servidores web integrados en esos dispositivos es una práctica común que proporciona acceso directo a ellos desde cualquier lugar y permite su configuración.
Aunque posible, las soluciones mencionadas anteriormente son obviamente más difíciles, más costosas y menos versátiles. Para resolver esto, elegir Linux es la opción más común, ya que estamos hablando de un sistema operativo de escritorio que recientemente se ha reducido significativamente para que pueda ejecutarse, y gracias a los micros que experimentan una evolución importante al mismo tiempo en los últimos años, todo en conjunto, establece el entorno necesario de tal manera que el desarrollo de software de comunicación compleja en microcontroladores pequeños se vuelve más fácil debido a las funciones de alto nivel proporcionadas por el propio SO. Usar este sistema ofrece una gran ventaja en términos de programación, ya que estamos hablando de un SO multiplataforma que permite cambiar entre plataformas con apenas cambiar algunas líneas de código. En general, el código utilizado en Linux es compatible con POSIX.
Sin embargo, los requisitos mínimos del SO son mucho más altos que los de las dos soluciones mencionadas anteriormente, ya que demandan más potencia y memoria para su correcto funcionamiento, lo que aumenta exponencialmente los costos de producción de la solución comercial y dificulta el acceso incluso al hardware más sencillo, ya que estás obligado a pasar por el SO para cada recurso del micro debido a que este último los gestiona todos, y obliga al programador a crear un controlador, una tarea nada fácil, siempre que necesites acceder a algún recurso que el SO no soporte.
Otro factor a considerar es el entorno de desarrollo. Si tu única intención es programar para crear un dispositivo ‘independiente’, el proceso en sí no presenta normalmente ningún problema. Simplemente aprendes a usarlo y eso es todo. Sin embargo, si tu propósito es crear algún dispositivo con un sistema de comunicación, entonces tendrás que conectarlo a una aplicación, ya sea de computadora o de teléfono inteligente, y es ahí cuando comienzan los problemas. En primer lugar, el código generalmente es incompatible entre plataformas; en segundo lugar, la programación del dispositivo normalmente se realiza de una manera particular, en un entorno que a menudo es bastante diferente del entorno que vas a usar cuando programas la aplicación en la computadora o el teléfono inteligente, lo que te hace perder tiempo yendo de un entorno a otro, sin mencionar la ausencia de compatibilidad de código y el hecho de que depurar en un micro todo el tiempo tiene mayores limitaciones que hacerlo para el mismo código pero desde una computadora.
Hace tres años, decidimos crear ExOS para cambiar esa situación.
La idea detrás de ExOS es que, ahora, solo necesitarás enfocarte en tu dispositivo de aplicación. No pierdas tiempo aprendiendo cosas nuevas o probando hardware. Aquí presentamos las características clave de ExOS:
De aquí en adelante, comenzar tu proyecto de hardware será realmente fácil ya que no necesitarás ningún hardware en absoluto.
Simplemente usando tu computadora puedes codificar y probar tu proyecto de hardware gracias a que ExOS es compatible con POSIX. Comienza tu código directamente en tu computadora y, si el proyecto cumple con tus expectativas, pasa al siguiente paso y construye el mismo código en el hardware real. Ya sea usar una placa de prototipo comercial o diseñar tu propio hardware. Las posibilidades son infinitas. No estamos restringidos a ningún hardware específico; elige el que te interese, pero no te preocupes si necesitas cambiarlo, ExOS lo hace posible porque hemos creado un soporte multiplataforma incorporado para que no tengas que cambiar tu código una y otra vez.
ExOS admite dos tipos diferentes de programación: programación dinámica, que es toda la programación POSIX basada en memoria dinámica; y programación estática, que usa memoria estática. Esta última es ampliamente utilizada en el mundo del hardware, ya que, en un gran número de casos, los microcontroladores tienen recursos realmente limitados y los costos de agregar memoria dinámica son potencialmente caros en términos de recursos del procesador. Por lo tanto, para esos casos, todas las llamadas POSIX tienen su contraparte en las llamadas de ExOS, siendo la única diferencia entre ellas, la adición de otro parámetro para pasar por referencia la memoria estática para trabajar. Todos los recursos de ExOS, como USB, sockets, hilos, etc., se pueden programar de forma estática o dinámica e incluso pueden alternarse durante el proceso de programación sin distinción.
Una de las principales razones por las que tuvimos en cuenta el estándar POSIX es la abundante documentación existente en estos días. Internet está lleno de tutoriales, documentos, etc., que facilitan mucho el aprendizaje de cómo programar prácticamente cualquier cosa. Muchos sistemas operativos destinados a computadoras son compatibles con POSIX, ejemplos de ello son Linux o OSX, por lo tanto, ya tenemos mucha información al respecto y, sin embargo, el SDK que proporcionamos estará acompañado de sus correspondientes tutoriales completos y amplia documentación.
¡Acceso directo a hardware y servicios del SO, todo a la vez!
Aunque ExOS se centra en la programación POSIX, no quisimos cerrarnos puertas restringiendo el acceso al hardware, como sucede con un SO de escritorio común. El acceso se puede realizar tan simplemente como ir directamente al micro que deseas utilizar para, por ejemplo, habilitar o deshabilitar un pin.
Nuestra motivación siempre ha sido, principalmente, que los desarrolladores pudieran tener acceso a hardware no restringido. De hecho, en el fondo, no estamos desarrollando exactamente una aplicación para computadoras, lo que realmente hacemos es desarrollar un dispositivo electrónico que ejecuta la aplicación que estamos desarrollando en ese momento. Compartir recursos con otras aplicaciones paralelas ya no será necesario.
Dentro de ExOS, encontramos varios niveles de acceso al hardware y, dependiendo de los requisitos del producto a desarrollar, el desarrollador podrá decidir cuál es el nivel de acceso que desea elegir.
El nivel más básico de todos es el acceso directo a los recursos del microprocesador, por ejemplo: GPIO, memoria, registros, etc. Este es el nivel en el que se accede directamente al micro en cuestión sin tener que pasar por ninguna capa de ExOS. Sin embargo, dicho acceso es adecuado exclusivamente para aquellos casos en los que se desea realizar acciones simples o bastante fáciles, como activar un pin, un solo comando cuya operación en capas superiores haría inevitable el uso de la mayor cantidad de código posible. Por el contrario, esta opción no se recomienda cuando se realizan operaciones más difíciles, ya que su acceso está restringido al micro desde el que se está programando. Si cambiamos el micro en esta situación, es probable que esa parte del código sea incompatible con el nuevo. Como resultado, restringir su uso a acciones simples sería muy fácil para el nuevo micro cuando llegue el momento de cambiar códigos.
El siguiente nivel es la capa de abstracción de hardware (HAL). Esta capa permite que las llamadas que se utilizan sean multiplataforma sin requerir muchas líneas de código. Esta es la capa en la que se basa ExOS y la más adecuada para usar los periféricos básicos del micro, como RS232, CAN, buses SPI, etc., u otros periféricos como los temporizadores, ADC, etc. Esta capa no se recomienda, por otro lado, para recursos altamente complejos como sockets, USB, Bluetooth, etc., ya que es mucho más difícil de usar y porque dichos recursos generalmente implican programar pilas como el TCP/IP que ExOS ya proporciona en el siguiente nivel de acceso.
El tercer nivel de acceso al hardware tiene lugar a través de los servicios del sistema, tal como sucedería en cualquier programación de aplicaciones de escritorio. Mediante estos recursos, la programación de sockets, Bluetooth, USB, etc., se vuelve fácil ya que toda la abstracción de hardware y las lógicas de operación de esos periféricos ya están incluidas en el estándar ExOS. Así, por ejemplo, programar un código que actúe como servidor en una red Ethernet es tan fácil como si lo hicieras usando un SO de escritorio como Linux. De hecho, utilizando la programación POSIX, el código sería exactamente el mismo. Esta es la capa de acceso máximo y la que recomendamos cuando se desea usar periféricos y protocolos más complejos.
La ventaja más importante que define a ExOS es que no será necesario elegir la capa de abstracción que deseas usar mientras programas. Dentro del propio código, es perfectamente posible tener acceso a cualquiera de las tres capas en cualquier momento. Es decir, sería factible crear un servidor TCP/IP en el microcontrolador utilizando los servicios de la capa del sistema para gestionar sockets y, una vez recibido el paquete de datos, podemos enviarlo a través del bus CAN usando la API de la capa de abstracción de ExOS y luego activar un LED accediendo directamente al pin del micro al que está conectado el LED, para ver el momento en que la placa está recibiendo los datos.
Ejemplo de código real ExOS completamente funcional en un micro LPC177x, como se mencionó anteriormente:
Increíble, ¿no? ¡¡Solo unas pocas líneas de código para lograrlo!!
Una plataforma unificada donde no tendrás que trabajar con varios entornos de desarrollo
¿No odias tener que desarrollar una solución combinada usando una aplicación para smartphone o computadora, así como hardware embebido en varios IDEs? ¿Y tener que codificar tu aplicación de smartphone o computadora en un IDE como Xcode o Visual Studio y luego cambiar a otro IDE como Microchip, CodeWarrior, CrossWorks, etc., para desarrollar el hardware? ¡Nosotros tampoco lo soportamos!
Hoy en día, los entornos más utilizados para la programación de aplicaciones, tanto de escritorio como de movilidad, son Xcode y Visual Studio. Ambos son entornos de programación con muchos años de experiencia a sus espaldas. Estos dos tienen una gran cantidad de recursos para el desarrollador tanto en términos de programación como de depuración.
Adaptamos el SDK de ExOS para que sea posible programar en Xcode o Visual Studio sin cambiar de entorno al implementar la función deseada en el micro. De esta manera, puedes tener ambos proyectos en la misma solución, la aplicación móvil/escritorio que deseas conectar y la aplicación que ejecutarás en el hardware real.
Para que la depuración sea fácil, el SDK permite 4 formas de depuración y prueba de la aplicación que se está desarrollando a través de ExOS para saber, lo antes posible, si la funcionalidad prevista es correcta o si su código está bien hecho.
En algunos casos, para todo el hardware que utiliza principalmente servicios del SO, como sockets, puertos seriales, USB, etc., puedes codificar directamente en tu computadora utilizando POSIX. Esto ayuda enormemente cuando se depura en una computadora con más recursos y luego, una vez que el desarrollo está hecho, la única parte que queda sería compilar el mismo código en el hardware a través de ExOS, sin cambiar una sola línea de código. Ese sería el caso, por ejemplo, de programar un adaptador Ethernet a Serial donde sería suficiente usar los servicios del SO.
En otros casos, realizar estas pruebas en la computadora no sería posible ya que puede haber ciertos requisitos de hardware especial que la computadora no tiene. Dada esa situación, tenemos dos opciones: La primera es el simulador y la segunda es ejecutar el código en el dispositivo nativo.
Sobre el simulador. La simulación de elementos de hardware y periféricos que no existen en la computadora se puede hacer a través de controles y pantallas virtuales incluidas en el SDK; o bien, el simulador se puede conectar a un dispositivo en modo ‘maestro-esclavo’, leyendo y escribiendo los valores de los periféricos como, por ejemplo, LEDs, ADC, etc., en la placa real. En este caso, no estaríamos emulando ningún micro específico, y se recomendaría específicamente depurar las lógicas de programación ya que la computadora donde se está ejecutando tiene más herramientas para dicha depuración.
Y por último, pero no menos importante, necesitamos hablar del hardware en sí. Hay situaciones en las que emular todo el hardware que se está desarrollando resulta imposible. Cuando esto sucede, el IDE puede ejecutarse y depurarse directamente en la placa con la que estamos trabajando. Obviamente, la depuración estará restringida a los recursos disponibles para el micro que se está utilizando para ese propósito.
La mayoría de las placas que soporta nuestro SDK pueden servir como enlace para el simulador funcionando como una placa esclava de la primera o actuando como una placa independiente capaz de grabar el programa en la propia placa y sin tener que pasar por el simulador constantemente. Sin embargo, aunque tenemos dos placas de desarrollo, una fundamentalmente básica y otra avanzada, para procesar video y audio, en realidad sería factible usar cualquier otra placa comercial del mercado ya que ExOS no se limita solo a nuestras propias placas.
Otra herramienta que incluye el SDK es un asistente para la configuración de las placas de desarrollo. Esto permite crear el BSP como si fuera la tarea más fácil del mundo, incluso cuando no tengamos la configuración electrónica de esa placa en ExOS.
Acceso a toneladas de bibliotecas y servicios
Para hacer posible la transición de una idea a un prototipo, y realizar las pruebas adecuadas para verificar su viabilidad de manera flexible y rápida, implementamos una gran cantidad de bibliotecas de código, servicios, módulos, frameworks y controladores en ExOS para que puedas centrarte únicamente en probar tu idea. En cualquier caso, si sucede que algún servicio periférico o controlador, a pesar de todo, no estuviera incluido, crear la parte faltante sería bastante fácil.
Dentro de ExOS encontramos, en primer lugar, la API del sistema, que es el conjunto completo de llamadas que conforman el estándar POSIX, así como la versión estática de esas llamadas en ExOS. Como parte de esta clasificación tenemos sockets, temporizadores, hilos, semáforos, bloqueos, mutex, colas, etc. En la API del SO, también podemos encontrar servicios adicionales que no existían originalmente en el estándar y que son útiles para programar eventos, como el dispatcher.
En segundo lugar, tenemos los controladores. Para evitar que busques código de terceros para implementar periféricos, incluimos muchos controladores. Tenemos controladores para la mayoría de los dispositivos:
- USB: teclado, ratón, webcams, impresoras, memorias USB, ftdi, etc.
- Sistemas de archivos: fat, jfs, ext2, fat32, nfs, etc.
- Buses: RS232, RS485, CAN, SPI, I2C, etc.
- Codecs: NTSC, PAL, MP3, mp4, amr, etc.
- Periféricos: pantallas táctiles, ADC, etc.
- Comunicación: Bluetooth, Ethernet, WiFi, ZigBee, etc.
En tercer lugar, están los servicios. Estos no deben confundirse con los servicios del sistema, sino que se trata de aquellos servicios en los que se encuentran todos los servicios de red más comunes, como por ejemplo, DHCP, FTP, HTTP, SSH, BONJOUR, DNS, etc. Todos ellos han sido implementados y optimizados para su perfecto rendimiento en la aplicación que estás ejecutando, reduciendo al máximo los recursos que consumen.
Y finalmente, debemos hablar de las bibliotecas y frameworks. En ciertas ocasiones, cuando ya te has acostumbrado a programar usando lenguajes de alto nivel, generalmente no solo se usa el lenguaje en sí, sino también las bibliotecas incluidas en el entorno. Con este propósito, en nuestra situación particular, hemos estado usando C/C++/Obj-C para nuestros proyectos de desarrollo durante tanto tiempo que decidimos hacer un wrapper para ExOS de las bibliotecas/frameworks más utilizados al programar para OSX y iOS, como por ejemplo, CoreFoundation, CoreNetwork, CoreGraphics, CoreBluetooth, etc., para que incluso pudiéramos usar el código de alto nivel empleado en una aplicación de OSX/iOS.
Una de las bibliotecas más importantes que incluimos en ExOS es la biblioteca de protocolo de accesorios de Apple (iAP). Con esta biblioteca, crear un accesorio para comunicarse con un iPhone, iPad o iPod se vuelve muy fácil. Dentro del código solo tienes que abrir el protocolo como si fuera un dispositivo y eso es todo. Puedes leer y escribir desde y hacia el iPhone.
Sólo un pequeño ejemplo de código:
Abra un protocolo iAP que haga eco de los datos del iPhone
ExOS ha sido diseñado y programado en C, al igual que todas las bibliotecas que incluye, pero, actualmente, también soporta los lenguajes C, C++ y OBJ-C, y planeamos ampliar su desarrollo para que sea posible manejar incluso más frameworks y no solo las bibliotecas en C, sino también las de OBJ-C como UIKit o AppKit, para poder diseñar incluso interfaces de usuario en el propio Xcode.
Y, por supuesto, no podíamos olvidar a los programadores de Windows acostumbrados a trabajar con el lenguaje C#. También planeamos soportar el lenguaje C# y la creación de interfaces usando el propio Visual Studio.
Kits de Desarrollo
Actualmente, tenemos disponibles 3 kits de desarrollo:
Kit de desarrollo Bluetooth
Como se mencionó, es el kit más básico de todos. Es el TinyBLE, una pequeña placa que incluye un chip Bluetooth 4.0 LE. A través de este kit, puedes programar cualquier cosa que se te ocurra utilizando BLE, como iBeacons, mandos a distancia, etc. La placa tiene varias entradas y salidas de expansión, así como soporte para una pila de botón que la hace ligeramente independiente de la conexión de energía, además de un conector para un bus de comunicación.
Para proporcionar mayor funcionalidad al TinyBLE, agregamos otras dos placas en el mismo kit: una placa con dos salidas (relevadores), 6 entradas digitales/analógicas, así como dos puertos RS232 y el bus de comunicación; y la otra placa, una pequeña placa de sensores, como por ejemplo, el sensor de temperatura y luz, de modo que, a través de estas dos placas, consigas un rango de posibilidades mucho mayor en cuanto a las funcionalidades que puedes implementar.
Kit de desarrollo principal
Este kit incluye una placa que contiene una gran cantidad de periféricos, lo que hace posible programar muchas cosas increíbles. Comprende los siguientes periféricos: RS232, RS485, CAN, USB, Bluetooth LE, Ethernet, WiFi, 3G/GSM, SPI, I2C y un conector especial donde puedes conectar el chip de desarrollo MFi* de Apple para crear accesorios para iPhone, iPad o iPod. Además de lo anterior, incluye una pantalla LCD con soporte táctil. Nota: *El chip MFi NO está incluido en el SDK ya que se requiere registrarse en el programa de desarrolladores MFi de Apple.
Esta placa tiene un bus de comunicación que se puede vincular a las placas del primer kit de desarrollo o del kit básico.
Kit de desarrollo de video y audio
Está destinado a usos más intensivos como, por ejemplo, el procesamiento de video. Esta placa es capaz de capturar y reproducir tanto audio como video. También tiene soporte de compresión y descompresión, así como soporte OSD y entradas y salidas PAL, NTSC, HDMI y Ethernet.
También incluye soporte de comunicación con las placas de los kits anteriores.
NOTA: Es importante destacar que, aunque proporcionamos los kits de desarrollo mencionados anteriormente, que creemos son muy completos para la mayoría de las aplicaciones, sigue siendo posible usar cualquier otra placa de desarrollo, incluso si es de otros fabricantes.
Consideración importante
ExOS no ha sido diseñado para convertirse en un sistema operativo de escritorio. Es decir, no puede manejar tener varias aplicaciones instaladas simultáneamente o ejecutarse al mismo tiempo (los servicios son casos especiales). ExOS está a medio camino entre programar “como si tuvieras un sistema operativo subyacente” y programar como si no lo tuvieras, accediendo directamente al hardware.
Ejemplo
ExOS puede ejecutarse perfectamente en una computadora Intel i386/i64 y, sin embargo, sin importar cuán poderosa sea la computadora e incluso cuando la aplicación ejecutada sea gráfica, solo podrá ejecutar esa aplicación, nada más. No habrá sistemas de archivos ni ventanas, etc.
Por otro lado, tiene sentido usar ExOS para ejecutarlo en una PC con procesador Intel para, por ejemplo, programar una aplicación en la que utilizarás todos los núcleos de la computadora al renderizar una escena 3D, ya que ExOS consume muy pocos recursos de la máquina en comparación con un sistema operativo de escritorio regular y, además, incluye soporte multi-núcleo.