Usb4all

De Proyecto Butiá
Revisión del 15:20 29 sep 2011 de Andres (Discusión | contribuciones) (Escribiendo un usermodule)

Saltar a: navegación, buscar

Motivación

La motivación de este proyecto se centra en lograr de una manera sencilla, la comunicación entre un sistema computador y un conjunto de dispositivos electrónicos no necesariamente pensados para interactuar con una computadora. Durante muchos años la única forma de interactuar con dispositivos externos desde a un computador personal (Personal Computer) (PC) fueron los puertos seriales y paralelos, esto llevo a que se utilizaran ampliamente en multiplicidad de dispositivos. Sus principales carácteristicas son su simplicidad de manejo vía software y facilidad de inclusión en distintos dispositivos. En la última década han aparecido nuevos medios o canales de comunicación, tales como Bluetooth, Fidelidad Inalámbrica (Wireless Fidelity) (WiFi), FireWire, Bus Universal en Serie (Universal Serial Bus) (USB), etc. Estos permitieron mejorar las velocidades de comunicación y calidad de datos y lentamente tornaron a los puertos paralelos y seriales en obsoletos, hasta llegar al día de hoy en que se obtienen sólo de manera opcional en los nuevos PC. Dentro de todas estas nuevas tecnologías que aparecieron la que tuvo mayor aceptación y difusión entre los usuarios fue el USB, debido a su facilidad y versatilidad de escenarios de uso. Esta simplicidad desde el punto de vista del usuario de los dispositivos USB tiene como contrapartida una mayor complejidad para los desarrolladores de software y hardware, lo cual es un gran problema al momento de interactuar con dispositivos electrónicos. Frente a estas adversidades que presenta el entorno actual aparece la necesidad de buscar una forma de reducir el grado de complejidad y conocimientos necesarios para poder desarrollar software que utilice la tecnología USB. Al mismo tiempo, se requiere una plataforma base que incorpore componentes de hardware reutilizables y que en conjunto formen una solución genérica para la comunicación con dispositivos electrónicos diversos. En el contexto de lo antedicho aparecen un conjunto de desafíos como son el desarrollo de controladores (drivers) y construcción de piezas de hardware que brinde una solución genérica reutilizable, desplazando el manejo de los casos particulares a componentes específicos. Esto proporciona el beneficio de evitar que cada vez que se necesite conectar un nuevo dispositivo, se comience desde cero. A su vez permite recuperar y potenciar la característica de facilidad de manejo que poseían los puertos seriales y paralelos, explotando todas las capacidades brindadas por USB.

Arquitectura

La arquitectura esta compuesta por diferentes componentes, los cuales van a permitir el funcionamiento del sistema desde lo concerniente al hardware como las abstracciones necesarias para manejarlo mediante software. Los componentes principales son:

USB4all Baseboard

USB4all Baseboard

Es una placa de entrada/salida configurable que se conecta por USB con un sistema computador. El proyecto USB4all es mucho más que una placa de E/S, en sí es una forma de modelar sistemas embebidos, siendo la placa de E/S un compomente que fue necesario construir para desarrollar la solución completa. Para la construcción de ésta placa se utilizó un microcontrolador PIC18F4550 de Microchip. Entre las características más destacadas en lo que concierne al proyecto se encuentra el soporte completo del estándar USB, pudiendose utilizar varias de sus características, como ser diferentes tipos transferencias y varios canales de comunicación (endpoints).

USB4all base firmware

Es el firmware más estático, brinda servicios a los usermodules para que puedan utilizar los recursos presentes en la baseboard (timmers, puerto USB, conversores A/D, etc) además de brindar las primitivas para el intercambio de mensajes entre el computador y el usermodule y realiza la gestión de los usermodules. Establece las bases para que los usermodules sean independientes del protocolo de comunicación computador/placa y de los detalles de hardware del microcontrolador utilizado. A su vez oferce un entorno de ejecución concurrente que permite instanciar de forma dinámica varios usermodules.

USB4all usermodule Son los componentes intercambiables del sistema que permiten encapsular la lógica de un dispositivo especifico y su protocolo de comunicación con las aplicaciones de usuario. Permite al usuario dar rápidamente soporte a un nuevo dispositivo de forma genérica, expandiendo de ésta manera las funcionalidades del USB4all basefirmware. Los user modules son los bloques principales sobre los que se construye la arquitectura USB4all. Exponen una API uniforme que es utilizada a modo de callbacks por el base firmware y también exponen los servicios que brindan los dispositivos. Es recomendable modelar cada uno de los dispositivos electrónicos conectados a la baseboard como un usermodule donde los servicios a exponer se mapean con las características del mismo, como ejemplo en el caso de un motor, sería esperable que expusiera servicios para moverse, cambiar la velocidad y el sentido.

Del lado del sistema computador se dispone de diferentes formas de interacción: Todas ellas implementan el protocolo USB4all, su objetivo es abstraer al usuario del mismo brindando una forma sencilla de utilizar el sistema, existiendo soporte para diferentes leguajes de programación. El objetivo principal de las bibliotecas utilizadas en el computador son las de permitir utilizar los servicios de los usermodules. Esta forma de trabajo permite desarrollar la lógica de interacción entre los diferentes dispositivos electrónicos dentro del sistema computador, con lenguajes de mayor abstracción, mejores herramientas de desarrollo, permitiendo generar un código con un nivel de mantenibilidad y abstracción mayor al que se lograría si todo estuviera embebido en el microcontrolador.

Uno de los componentes más usados actualmente es el bobot que persigue un enfoque genérico al igual que el proyecto USB4all y permite acompañar la extensibilidad de la placa USB4all mediante el uso de ciertos componentes propios de la arquitectura llamados drivers.

Protocolo de Comunicación

Grabando el Firmware

Para grabar el firmware se necesita disponer de un programador, como el picdem

En el firmware del microcontrolador se utiliza una versión modificada del bootloader de microchip, esto permite grabar


el botón más cercano al led es el de programación, el más cercano al microcontrolador es el de reset.

Id dispositivo USB4all

   Bus 002 Device 002: ID 04d8:000c Microchip Technology, Inc. 

id dispositivo Bootloader

   Bus 002 Device 003: ID 04d8:000b Microchip Technology, Inc.

Escribiendo un usermodule

tabla de referencias a user modules

Un usermodule debe cumplir con una API determinada, de esta manera es posible agregar las funcionalidades que él módulo expone, dentro del firmwarebase. Las operaciones principales que se deben implementar son las encargadas de atender los eventos de:

  • inicialización
  • liberación de recursos
  • configuración

Estas operaciones se ejecutan en determinados momentos del ciclo de vida de una aplicación USB4all, siendo la operación registrada al evento de inicialización invocada al abrir desde la aplicación el usermodule y la de liberación de recursos al cerrarlo, esto permite utilizar los recursos del microcontrolador solo cuando es necesario. La operación de configuración puede invocarse en cualquier momento para cambiar en caliente algún aspecto de configuración del hardware. A comenzar un usermodule se debe declarar cuales van a ser las funciones que van a atender estos eventos y el nombre del módulo para ser identificado desde el computador al listar los módulos presentes en la placa.

   #pragma romdata user
   uTab userBuzzerModuleTable = {&UserBuzzerInit,&UserBuzzerRelease,&UserBuzzerConfigure,"buzzer"};
   #pragma code

Donde user es el nombre de la sección y uTab es un estructura para almacenar las posiciones de memoria de las operaciones que exporta el módulo y su nombre.

Como argumento a la operación init se recibe el número de handler asignado al módulo, este número es utilizado como argumento en otras operaciones como ser setHandlerReceiveFunction la cual recibe por parámetro el handler y un puntero a la función encargada de manejar la recepción de datos. Otra operación similar es getSharedBuffer que recibe por parámetro el handler de módulo y retorna un buffer por el cual el módulo puede enviar datos a la aplicación que ejecuta en el computador. Un buen lugar para obtener éste buffer y registrar la función de recepción de datos es la operación encargada del evento de inicialización

 void UserBuzzerInit(byte i) {
    usrBuzzerHandler = i;
    // add my receive function to the handler module, to be called automatically when the pc sends data to the user module
    setHandlerReceiveFunction(usrBuzzerHandler,&UserBuzzerReceived);
    // initialize the send buffer, used to send data to the PC
    sendBufferUsrBuzzer = getSharedBuffer(usrBuzzerHandler);
}//end UserBuzzerInit


 void UserBuzzerReceived(byte* recBuffPtr, byte len){
      byte index;
      byte j;  
      byte userBuzzerCounter = 0;
      byte tiempo;

      switch(((BUZZER_DATA_PACKET*)recBuffPtr)->CMD){
        case READ_VERSION:
              //dataPacket._byte[1] is len
              ((BUZZER_DATA_PACKET*)sendBufferUsrBuzzer)->_byte[0] = ((BUZZER_DATA_PACKET*)recBuffPtr)->_byte[0]; 
              ((BUZZER_DATA_PACKET*)sendBufferUsrBuzzer)->_byte[1] = ((BUZZER_DATA_PACKET*)recBuffPtr)->_byte[1]; 
              ((BUZZER_DATA_PACKET*)sendBufferUsrBuzzer)->_byte[2] = BUZZER_MINOR_VERSION;
              ((BUZZER_DATA_PACKET*)sendBufferUsrBuzzer)->_byte[3] = BUZZER_MAJOR_VERSION;
              userBuzzerCounter = 0x04;
              break;  
              
        case PRENDER:
              ((BUZZER_DATA_PACKET*)sendBufferUsrBuzzer)->_byte[0] = ((BUZZER_DATA_PACKET*)recBuffPtr)->_byte[0]; 
              ((BUZZER_DATA_PACKET*)sendBufferUsrBuzzer)->_byte[1] = ((BUZZER_DATA_PACKET*)recBuffPtr)->_byte[1]; 
              buzzer_on();
              userBuzzerCounter = 0x02;
              break;  
        
        case APAGAR:
              ((BUZZER_DATA_PACKET*)sendBufferUsrBuzzer)->_byte[0] = ((BUZZER_DATA_PACKET*)recBuffPtr)->_byte[0]; 
              ((BUZZER_DATA_PACKET*)sendBufferUsrBuzzer)->_byte[1] = ((BUZZER_DATA_PACKET*)recBuffPtr)->_byte[1]; 
              buzzer_off(); 
              userBuzzerCounter = 0x02;
              break;  

        case BUZZER_TRIPLE:
              ((BUZZER_DATA_PACKET*)sendBufferUsrBuzzer)->_byte[0] = ((BUZZER_DATA_PACKET*)recBuffPtr)->_byte[0]; 
              ((BUZZER_DATA_PACKET*)sendBufferUsrBuzzer)->_byte[1] = ((BUZZER_DATA_PACKET*)recBuffPtr)->_byte[1]; 
              cantTicks1 = (byte)(((BUZZER_DATA_PACKET*)recBuffPtr)->_byte[1]);
              cantTicks2 = (byte)(((BUZZER_DATA_PACKET*)recBuffPtr)->_byte[2]);  
              cantTicks3 = (byte)(((BUZZER_DATA_PACKET*)recBuffPtr)->_byte[3]);
              boubleBeep(cantTicks1, cantTicks2, cantTicks3);
              userBuzzerCounter = 0x02;
              break;        

        case BUZZER_CORTO:
              ((BUZZER_DATA_PACKET*)sendBufferUsrBuzzer)->_byte[0] = ((BUZZER_DATA_PACKET*)recBuffPtr)->_byte[0]; 
              ((BUZZER_DATA_PACKET*)sendBufferUsrBuzzer)->_byte[1] = ((BUZZER_DATA_PACKET*)recBuffPtr)->_byte[1]; 
              cantTicks3 = ((BUZZER_DATA_PACKET*)recBuffPtr)->_byte[1];
              timeOutTicksBuzz = 1; // lo seteo timmer para que venza inmediantamente
              buzzerState = DELAY;  
              registerT0event(0, &buzzEvent);
              userBuzzerCounter = 0x02;
              break;    

        case RESET:
              Reset();
              break;
     
         default:
              break;
      }//end switch(s)
      if(userBuzzerCounter != 0){
            j = 255;
            while(mUSBGenTxIsBusy() && j-->0); // pruebo un máximo de 255 veces
                if(!mUSBGenTxIsBusy())
                    USBGenWrite2(usrBuzzerHandler, userBuzzerCounter);
      }//end if            
}//end UserBuzzerReceived

Bobot

bobot-server (version 2) es un servicio que permite acceder a aplicaciones y usuarios interactuar con dispositivos USB4all. Consiste en agente altamente portable y liviano, que exporta la funcionalidad de los dispositivos USB4all presentes de una forma fácil de usar. Ofrece dos métodos de acceso, uno optimizado para aplicaciones, basado en un socket y un protocolo facilmente parseable, y otro optimizado para ser usado por humanos, mediante un sitio web hosteado en el propio agente, el cual atiende en el puerto 2010. Puede descargarse bobot-server desde el git del proyecto butiá en sourceforge.

El proyecto USB4all se encuentra disponible bajo licencia GNU/GPL v2 en el repositorio sorceforge
Este proyecto surge originalmente como un trabajo de tesis de grado en Ingeniería en Computación de Aguirre, Fernandez y Grossy.