FreeRTOS7.1.0 y Olimex LPC-H2129

Necesitaba un prototipo fácil y rápido para una pequeña aplicación casera, y resulta que tenía a la mano la tarjeta Olimex LPC-H2129, y un “shield” y una tarjeta de relevadores tipo PLC  hechos en casa para dicha tarjeta. Comencé la aplicación y rápidamente me dí cuenta que lo mejor era utilizar un RTOS dada la naturaleza del proyecto, así que busqué el port de FreeRTOS para el LPC2129. No existe tal, así que adapté uno de los que vienen con la distribución, y rápidamente tenía un “hola mundo” con RTOS y mis tarjetas. Hasta ahí todo iba bien, pero me dí cuenta que el búzer de mi aplicación está conectado al pin P0.22, el cual se corresponde con el canal 0 del timer T0, MR0.  Requiero que el búzer esté en el pin P0.22 ya que tiene multiplexada la salida MAT0.0 de T0, y el búzer requiere PWM para emitir sonidos. Todas las demás salidas MATx.x de T0 y T1 no están disponibles dado el diseño del proyecto. El problema aquí es que el tick del RTOS también utiliza el canal 0, MR0 del timer T0. Habían tres opciones: 1. Cambiar de pin al búzer (no viable), 2. Cambiar el tick del sistema al timer T1 (rápido, pero sucio y poco elegante), y 3. Seguir utilizando el timer T0 para el tick del sistema, pero  en un canal diferente, por ejemplo, el canal MR3 (en teoría bastante simple, luego me dí cuenta que no lo era tanto).

Escogí la opción tres, pero tuvo sus dificultades, ya que por alguna razón el RTOS, así como “viene de fábrica, funciona perfectamente; sin embargo, los problemas se presentaron al cambiar de canal al tick del sistema.  Principalmente el sistema se colgaba luego de buscar la primera tarea disponible, y cuando no se colgaba entonces nunca entraba a la función void vTickISR( void ). Tras varias horas de depuración no encontraba la lógica para el mal funcionamiento del proyecto, así que busqué dentro del código de mis otros proyectos para ver cuál era la diferencia entre ellos que sí trabajan con las interrupciones sin problemas, y el RTOS que no lo estaba haciendo. En uno de ellos encontré algo que no está en el ejemplo para el LPC2000 que viene con el FreeRTOS; al principio asumí que tal vez no se requería porque sin él el sistema trabajaba bien utilizando el MR0 del T0, pero tenía que hacer las pruebas antes de descartar esa opción. El código que encontré en uno de mis proyectos  (el cual utilizo en todos ellos siempre que voy a utilizar interrupciones) es el siguiente :

void irq_handler(void) __attribute__((interrupt("IRQ")));
void irq_handler(void){
 // <-- Added to handle the IRQ

 void (*interrupt_function) ();
 unsigned int vector;

 vector = VICVectAddr; // Get interrupt vector.
 interrupt_function = (void(*) ()) vector;
 (*interrupt_function) ();
 VICVectAddr = 0; // Clear interrupt in VIC.
}

Este fragmento de código lo pegué en mi proyecto de FreeRTOS en el mismo archivo donde está la función main(), y ¡Oh, sorpresa!, todo comenzó a trabajar perfectamente, es decir, mi aplicación ya no se cuelga y está haciendo lo que se supone que debe hacer, correr varios procesos a la vez (en este momento solamente son dos). Aún tengo la duda del porqué con el canal MR0 trabaja sin el fragmento de código indicado, pero para el canal MR3 ya no. Cuando tenga tiempo lo voy a investigar, y más adelante voy a subir fotos de lo que estoy haciendo. Para una explicación más detallada sobre las interrupciones en el LPC2129 pueden ver esta entrada de mi blog. Por lo pronto ya puedo continuar con mi proyecto.

Anuncios

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s