Me gustaría obtener un consejo sobre el manejo de tareas en un firmware.
Tengo 3 tareas principales que hacer:
Escanear si se está presionando un interruptor o no.
Transmisión de datos vía SPI - A EEPROM
Transmisión de datos vía USB - A PC
Logré hacer una interrupción del temporizador cada 1 ms para ver si se presionó el interruptor o no. Pero la transmisión SPI ocurre solo cada 6 horas [tarda 50 ms en completarse] y la transmisión USB puede ocurrir en cualquier momento.
Mi pregunta es ¿cómo gestiono las tareas?
¿Debo deshabilitar la verificación del interruptor una vez que ingresa al estado 2/estado 3 y habilitarla después de que sale de los estados?
¿Cómo se supone que debo manejar tales situaciones?
La mayoría de las veces es bueno manejar las diversas cosas que el procesador necesita hacer con una combinación de interrupciones, tareas y eventos. En este caso, usaría una interrupción periódica de 1 ms para verificar y eliminar el rebote del interruptor, una tarea separada para manejar la transmisión USB del host y eventos u otra tarea para administrar la comunicación SPI. USB requiere cierto soporte continuo, incluso cuando en realidad no está enviando ni recibiendo nada en la capa de aplicación. Lo convertiría en una tarea separada o llamaría a la rutina de procesamiento en segundo plano USB regularmente desde el bucle de eventos principal.
Mi arquitectura habitual para tales cosas contiene las siguientes construcciones:
Esta interrupción también incrementa uno o más contadores de pulsos de reloj. A veces, las potencias de 10 son útiles, como 1 ms, 10 ms, 100 ms y segundos. La rutina de interrupción incrementa cada uno de estos según corresponda, y el resto del sistema los ve cambiar automáticamente.
Cada tarea se ejecuta como un ciclo infinito, excepto que llama a TASK_YIELD cuando no tiene nada que hacer de inmediato o después de una parte significativa del trabajo. Para recibir un flujo de bytes, es más conveniente escribir el código como si saliera y obtuviera el siguiente byte, aunque en realidad los bytes entran cuando entran. La rutina GET_BYTE generalmente comienza en un ciclo que llama a TASK_YIELD, verifica para que haya un nuevo byte disponible y, si no, vuelve al inicio del bucle. Cuando un byte está disponible, regresa con el nuevo byte. Esto permite que el código de la tarea principal llame a GET_BYTE en muchos lugares que dependen del contexto. Por ejemplo, al comienzo del bucle de la tarea principal, llama a GET_BYTE para obtener el código de operación del siguiente paquete. El código que se envía a la rutina para ese código de operación, que llama a GET_BYTE para obtener el primer byte de datos, etc.
Este mecanismo da prioridad a los eventos de manera efectiva y los marca en orden de prioridad alta a baja. Cada evento debe ser algo que sea relativamente simple de manejar y no requiera esperar nada más. Esto mantiene el ciclo de eventos principal llamando a TASK_YIELD regularmente. Si es necesario, divida los procedimientos más complicados en pasos independientes ejecutables inmediatamente, generalmente mediante el uso de una secuencia de indicadores de 1 bit para indicar que está listo para la siguiente fase de procesamiento. Por ejemplo, un evento podría iniciar una nueva lectura A/D. En lugar de esperar a que se haga eso, la rutina de interrupción A/D establece una bandera cuando hay una nueva lectura disponible. Ese es entonces un evento separado manejado por la rutina del evento principal.
Algunos eventos se basan en el tiempo. En lugar de establecer banderas para ellos en la rutina de interrupción del reloj, generalmente hago que la rutina del evento principal verifique los contadores de tic del reloj global cerca del comienzo del ciclo para decidir si es necesario activar algún evento relevante basado en el tiempo. Esto tiene varias ventajas:
Una gran cantidad de módulos de plantilla y algunos ejemplos están disponibles como parte de mi entorno de desarrollo de PIC . Esto incluye buenos administradores multitarea cooperativos para PIC 18 y PIC de 16 bits, plantillas para módulos de reloj, el bucle de eventos principal y mucho más.
Andy alias
Novato91
Andy alias
Cuchara
scott seidman
Novato91
Avín
Novato91