Hola a todos,
Hace un tiempo hice la catedra Sistemas Operativos en mi Facultad, pero todo era muy teórico, por lo que para comprender mejor las cosas hice un microkernel de un sistema operativo en tiempo real para un 16F84.
La idea era justamente obtener multitarea (ejecutar dos rutinas a la vez) en un PIC. En mi caso queria recibir y enviar por RS-232 al mismo tiempo (una UART Full-Duplex por soft).
Como se logra el truco: si bien es imposible que el Pic ejecute dos instrucciones al mismo tiempo, ejecutando una instruccion por vez de cada rutina, se logra el efecto de ejecutar las dos al mismo tiempo.
Para hacer esto lo primero que hay que hacer es dividir las rutinas en sus partes minimas. A estas partes minimas se las llama estados. Estos estados forman una maquina de estado finito. En cualquier libro de circuitos digitales secuenciales encontraran info sobre esto. Por lo general se las representa mediante un grafo dirigido.
Las rutinas asi divididas son ejecutadas en forma secuencial por una rutina principal que se llama el Planificador. En el caso de un PIC se simplifican mucho las cosas.
Por ejemplo supongamos que queremos ejecutar dos rutinas en multitarea donde cada rutina lee el estado de un pulsador en RA0 y otro en RA1. Cada pulsador tiene un pullup de 10K, o sea que normalmente se lee un 1 y al presionarlo se lee un 0.
Con esta configuracion se tienen los siguientes estados.
Estado 1: "Esperar que se presione el pulsador"
SI se presiono,
pasar al estado siguiente,
SINO,
volver.
Estado 2: "Se incrementa un contador (antirebote)"
SI el contador llega a una determinada cuenta,
se pasa al estado siguiente,
se vuelve el contador a 0,
volver,
SINO,
volver.
Estado 3: "Se ha presionado el pulsador y termino el tiempo de rebote
hacer algo util, por ejemplo encender un led"
encender un led,
pasar al estado siguiente,
volver.
Estado 4: "Esperar que se suelte el pulsador"
SI se solto,
pasar al esto siguiente,
volver,
SINO
volver.
Estado 5: "Se incrementa el contador anterior (antirebote)"
SI el contador llega a una determinada cuenta,
se vuelve el contador a 0,
se vuelve al estado 1,
volver,
SINO
volver.
En la practica el estado de cada rutina se guarda en un registro y en otro el contador de rebote. Por lo que cada rutina utiliza dos registros: Estado y Contador.
La rutina del planificador llama de forma continua a las dos rutinas de forma secuencial :
INICIO:
Llamar a la subrutina del pulsador 1.
Llamar a la subrutina del pulsador 2.
IR A Inicio
Hay que notar que a las rutinas se entra, si hay algo que hacer se hace y se sale, de esta forma se esta entrando y saliendo de cada rutina en forma continua. Cuando mas corto sea lo que haya que hacer mejor, ya que se logra mayor velocidad de respuesta del sistema.
En la practica para ejecutar cada estado se utiliza una tabla de saltos controlada por la variable Estado:
MOVF Estado, W
ADDWF PCL
NOP
GOTO Puls1_Estado1
GOTO Puls1_Estado2
GOTO Puls1_Estado3
Puls1_Estado1:
.......
RETURN
Puls1_Estado2:
.......
RETURN
Y asi sucesivamente... Al trabajar con tablas hay que tener en cuenta si no se traspasa el limite de cada pagina de la memoria de programa, y antes es mejor setear los bits de mayor peso del Contador de Programa, pero lo simplifiqué para mostrar el concepto.
Bueno con esta tecnica logré excelentes resultados, no solo para leer pulsadores, sino tambien teclados matriciales, recepcion y transmision serial y otras cosas mas.
Una cosa interesante es agregar un bit como bandera que permita habilitar o deshabilitar la subrutina. De esta forma se entra a la rutina, pero si el bit esta en 1, significa que no se debe ejecutar o que esta deshabilitada, por lo que se sale inmediatamente.
De esta forma se puede controlar la ejecucion simultanea de cualquier numero de rutinas y cualquier subrutina puede habilitar o deshabilitar a las otras desactivando o activando la bandera.
Bueno, espero que les hay resultado interesante.
Pronto voy a poner el fuente completo en assembler para que lo vean mejor, pero desde ya les digo que ademas de ayudarme a aprobar Sistemas Operativos me hizo ver que los Pic programados de la forma tradicional gastan mucho tiempo esperando algún evento, pero de esta forma ese tiempo se puede aprovechar para hacer otras cosas, por lo que se potencia el pic y pareciera que puede hacer todo al mismo tiempo !
En realidad SI SE PUEDE LOGRAR MULTITAREA EN UN PIC16F84!
Con respecto al sueño del pibe, la forma anterior sirve para cualquier micro, tenga o no tenga interrupciones. En realidad si tiene interrupciones se pueden hacer mas cosas o mejores, en especial si hay tareas criticas. Por ejemplo con la interrupcion del timer se puede asegurar que una rutina se ejecute exactamente cada cierto intervalo, o con la interrupcion externa que alguna otra se ejecute de inmediato en respuesta a un evento externo.
De todas formas el principio es similar. Por ejemplo la interrupcion externa puede cambiar de estado de una subrutina, o la del timer se puede utilizar para determinar intervalos de tiempo y saber cuando se debe enviar o recibir el siguiente bit de una comunicacion RS-232, por ejemplo.
Para apreciar mejor las diferencias de un Sistema Operativo en Tiempo Real (RTOS) con interrupciones y sin ellas les aconsejo la Nota de Aplicacion 585:
http://www.microchip.com/1010/suppdoc/appnote/all/an585/index.htmEs un poco densa al principio pero fijense en las cosas, o subrutinas que se pueden ejecutar al mismo tiempo en un pic con interrupciones y en otro sin ellas.
Espero que les sirva.
Téc. Claudio J. Pérez
Ciberar-Sistemas & Desarrollos
Jujuy-Argentina