- electronica-2
- internet
Comunicaciones en microcontroladores: Un ejemplo
Esto es un pequeño apunte mientras estudio un tema de comunicaciones en microcontroladores.
Las pilas de protocolos de comunicaciones en microcontroladores presentan algunos problemas en su implementación. Como sabéis la comunicación dentro de cualquier red se consigue utilizando una pila de protocolos que controlan diferentes ámbitos de la comunicación, en la parte de microcontroladores estas capas de la pila de protocolos se reducen a 3 o como mucho a 4, de abajo a arriba: nivel físico, de enlace, de red y de aplicación. Por encima del nivel de aplicación se encuentra el programa de usuario y por debajo del nivel físico el cable o el aire por donde se transmiten las ondas.
Lo problemática de programar este tipo de pilas viene cuando queremos comunicar información de una capa a otra. Si utilizamos C para programar (lo más común) tendremos que separar cada capa en un módulo y llamar de uno a otro mediante funciones declaradas en los archivos de cabecera. Pero cuando el tránsito de información se produce de abajo a arriba en la pila ocurre un problema, la recepción se produce de forma asíncrona mediante una interrupción, por eso la forma más eficiente de realizar esto es usando un flag que se active cuando se reciba un mensaje y una función callback, para realizar el procesamiento.
Una función callback es una función que se llama de arriba hacia abajo, pero en realidad está enviando información de abajo a arriba.
Para que me quede más claro el tema he buscado un ejemplo y he aprovechado que quería mirar el port de Contiki OS para Arduino. Este port utiliza como capa física los famosos chips XBee, baratos y fáciles de utilizar.
Contiki no sólo provee de una capa de red IPv6 si no que además proporciona la capa de aplicación CoAP. Me gustaría saber si se puede portar esto a Pinoccio, abaratando aún más la plataforma.
Así que me he puesto manos a la obra, me he bajado el código:
git clone https://github.com/telecombretagne/Arduino-IPv6Stack
if(c != NULL) {
/* If we were called because of incoming data, we should call
the reception callback. */
if(uip_newdata()) {
/* Copy the data from the uIP data buffer into our own
buffer to avoid the uIP buffer being messed with by the
callee. */
memcpy(databuffer, uip_appdata, uip_datalen());
/* Call the client process. We use the PROCESS_CONTEXT
mechanism to temporarily switch process context to the
client process. */
if(c->receive_callback != NULL) {
c->receive_callback(c,
&(UIP_IP_BUF->srcipaddr),
UIP_HTONS(UIP_IP_BUF->srcport),
&(UIP_IP_BUF->destipaddr),
UIP_HTONS(UIP_IP_BUF->destport),
databuffer, uip_datalen());
}
}
}
Como podéis ver se utiliza la función uip_newdata() como el flag del que he hablado antes, además se puede observar cómo si existe una función callback en ‘c’ (la estructura que se utiliza para la comunicación) ésta se ejecuta pasándole los datos de la misma conexión y los que necesite para el nivel inferior, que es el nivel IP.
Como hemos podido ver, en las implementaciones de sistemas de comunicaciones complejos como este caso se utilizan estos métodos para solucionar los problemas de implementación que pueden surgir.