Respecto a los 50ms o 100ms que decis, creo que es demasiado tiempo, puesto que una instruccion con un reloj de 4Mhz tarda en ejecutarse un micro-segundo, por lo que en 50ms, se ejecutarian unas 50.000 instrucciones que seguramente seria todo un proceso entero y no obtendriamos ninguna concurrencia.
Como dice pacala, deberiamos ir por partes, lo primero en lo que estoy trabajando es en ejecutar interrupciones por desbordamiento del TIMER0 cada pocos micro-segundos, para ello uso un divisor de frecuencias=1, y en la salida de la interrupcion pongo el timer0 a 255, ya que el desbordamiento se produce cuando pasa de 255 a 256. Haciendo esto, consigo que se ejecute la interrupcion cada 15-20 instrucciones con un reloj a 4 MHz.
Anoche hice un programa muy simple, que realizaba siempre la misma instruccion (sumar 1 a un contador) en un bucle infinito, y la interrupcion cuando se ejecutaba ponia dicho contador a 0, asi podiamos ver en un LCD (este ejercicio en Proteus funcionaba bastante bien y era bastante explicativo) el numero de instrucciones que se ejecutaban antes de llegar a una interrupcion.
Todo se basa en la siguiente formula:
Temporizacion=4 * Tosc *(256 - valor inicial del Timer)*Divisor de Frecuencia
Y con las variables que jugamos principalmente son "valor inicial del Timer" y "Divisor de Frecuencia", ya que el periodo del oscilador (Tosc), al ser el inverso de la frecuencia, creo que si le bajamos, disminuye nuestra temporizacion, pero subimos la frecuencia, por lo que se ejecutarian las instrucciones mas rapido, y por tanto no adelantamos nada.
A menor temporizacion del TIMER0, se podria obtener una mayor concurrencia SIMULADA (puesto que estamos trabajando solo con un micro).
El siguiente paso a mi juicio, seria hacer que con cada interrupcion se vaya modificando el vector de interrupcion, para conseguir tener en vez de rutinas de interrupcion, procesos que se ejecutan de forma concurrente. Es decir, usar como rutina de interrupcion, algo tan simple como un ORG(usando directivas de ensamblador) hacia la direccion de memoria del siguiente proceso, y a la vez una modificacion de la direccion de memoria 004 donde se encuentra el vector de interrupcion con el ORG al proximo proceso que se debera ejecutar concurrentemente, y por ultimo inicializacion del TIMER0 a 255,y otro cambio del vector, y todo esto de manera ciclica para conseguir la concurrencia. Es decir, nuestro proceso de interrupcion kedaria asi:
#INT_RTCC
void cambio_proceso()
{
uso de una sentencia ORG para tras la interrupcion dirigirnos al siguiente proceso ;
modificacion de la sentencia anterior, para que el ORG apunte al proceso que se ejecutara cuando se produzca la siguiente interrupcion;
Inicializacion del TIMER0 a 255 para conseguir una mayor concurrencia SIMULADA;
}
Una vez que tuvieramos concurrencia simulada, pasariamos a implementar los semaforos, para sincronizar los procesos concurrentes
Todo esto lo he pensado, leyendo unos pocos libros, y haciendo 20 o 30 programas en C, asi que no soy ni mucho menos un experto en el tema, es simplemente una idea que puede no llevar a ninguna parte.
Un saludo