Sunteți pe pagina 1din 39

Sistemas Operativos para microcontroladores

RTOS
para

PIC
INTRODUCCIN:
Gracias a la labor del amigo Reinier Torres Labrada, del foro sobre
microcontroladores TODOPIC, ponemos en uControl esta Introduccin a los
Sistemas Operativos para Microcontroladores.
Realmente, Reinier esta haciendo un muy buen trabajo con este tema, y debido a
que no hay demasiada informacin sobre RTOS para PIC en espaol, es que vamos
a ir recopilando en esta pagina sus post sobre el tema. Como podrn ver, abundan
los ejemplos, y sus explicaciones son muy claras.

NDICE:
> Introduccin
> Presentacin de la gua
> Un poco de teora sobre los Sistemas Operativos (SO)
> Diferencias entre usar un SO o usar las libreras del compilador de turno
> Qu es un Sistema Operativo?
> Clasificacin de los SO
> Introduccin al RTOS de CCS
> Funciones del RTOS
> Controlando la ejecucin de las tareas
> Yield vs delay
> Coordinar para no daar
> En sus marcas, listos, FUERA!
> RTOS mail
> Interrupciones! A M!
>
Volviendo sobre nuestros pasos
>
Las condiciones de competencia
> Datos de Contacto
> Bibliografa
> Descarga este documento en formato PDF (Puede no estar totalmente completo)

> Presentacin de la gua:


Las siguientes son palabras de Reinier, presentando en el foro su idea de armar esta
Introduccin a los Sistemas Operativos para Microcontroladores:

"Hola amigos
He visto que en el hilo "RTOS para PIC GNU" ha aparecido una interesante controversia
sobre los RTOS, sin embargo lo que ms curioso me resulta es que muchos no conocen
prcticamente nada sobre el tema, y como aqu todos estamos para aprender y
compartir lo poco que sabemos, quisiera comenzar por explicar algunos de los
principios bsicos de los SO y como podemos aplicarlos al campo de los
microcontroladores.
Espero que esta nueva idea sea de utilidad y despierte el inters en muchos de
ustedes. Yo soy muy nuevo en este campo de los SO y los microcontroladores, pero
con la ayuda de ustedes podremos hacer muchas cosas interesantes y beneficiosas
para todos.
De hecho todava no he comenzado a utilizar ningn RTOS o algo parecido para meter
en un PIC, ni siquiera me he metido con el cdigo de ningn SO, pero en la maestra
que estoy cursando tengo los SO (desde la ptica del diseo) como asignatura obligada
y no quisiera que despus de un montn de horas delante de un profesor que produce
ms sueo que inters por su asignatura (aunque el tema es interesantsimo), todo
ese conocimiento se quedara en la nota al final del semestre.
Bueno amigos... sin ms muela (prembulo) comencemos a trabajar"
[Volver al ndice]

> Un poco de teora sobre los Sistemas Operativos (SO)


Haciendo un poco de historia, y los ms aejaditos lo saben mejor que yo que soy un
nio de 26, los SO aparecieron ms o menos por all por los 60.
Lo que ocurri por aquel entonces, cuando las computadoras, eran tan poderosas
como nuestros PICs (algunos de gama alta son hasta ms poderosos que aquellas
computadoras), era que muchos programadores (matemticos locos la mayora), no
estaban interesados en conocer los detalles de las interfaces, controladores y dems
cacharros electrnicos que adornan a una computadora, y por otro lado algunos
programadores ya haban escrito controladores para esos dispositivos y por tanto los
que venan detrs simplemente queran utilizarlos y ya (algo parecido a lo que
hacemos en el foro).
Pues bien, con el tiempo se acumularon programas tiles para manejar dispositivos y
tareas complejas que deban programar personas no interesadas en la electrnica,
entonces la gente, que trabajaba en equipo, organiz todo aquello de manera que los
programadores, los programas y el hardware (HW) pudieran coexistir sin que se
produjera una guerra hubiteana (guerra en la que los hombres y los bits se pelean
hasta que los hombres se mueren de alguna clase de infarto o pierden a la mujer).
Surgieron as los primeros intentos de crear un SO y los hombres mantuvieron la Paz
sobre la tierra y tambin la guerra fra, aunque las cosas se calentaran a intervalos.
Pas el tiempo y lleg Bill Gates con DOS y luego Windows y Steve Jobs con su Mac,
unos tipos ms listos y cabrones que ingenieros o programadores. y despus tambin
apareci Linus Torvalds con Linux, uno que estaba ms loco que El Quijote y entonces
las personas corrientes creyeron que en el mundo solo existen a lo sumo tres SO
(Windows, Mac, y Linux), pero no es as hay un montn de SO, algunos muy poderosos

y otros no tanto, dependiendo de en que lugar y para que se hayan diseado.


Como es lgico suponer, en la parte de la historia que les acabo de contar est el por
qu los SO son tiles, pero eso lo iremos viendo poco a poco porque hay muchas
formas en las que un SO nos puede servir. Vamos a ver algunas:
1) Un SO convierte a las computadoras en equipos tiles.
Pone una o varias capas de Software (SW) sobre el HW, y con eso podemos escribir
programas y utilizar programas ya escritos por otros para hacer otros programas
escritos por nosotros mismos, sin tener que meternos en detalles tales como bueno
ahora mi procesador de textos ya trabaja y como guardo el documento?.
Seguramente si usted le dice al programador del procesador de texto que para guardar
el documento tiene que tirarse meses escribiendo las rutinas que guardan el doc.
seguramente le da un ataque.
2) Un SO es una herramienta poderosa en la gestin de procesos.
Nosotros mismos cuando programamos los PICs tenemos que leer el puerto serie,
escribir en una LCD, controlar el motor y todas esas cosas las hacemos a la vez. Pero
cada una de esas tareas podemos considerarla un proceso, y un SO puede ayudarnos a
gestionarlos eficientemente, aprovechando al mximo el procesador. Por ejemplo en
vez de poner al PIC a esperara a que el motor se mueva un poco poniendo una
demora, podemos utilizar ese tiempo en ir escribiendo un poco en la LCD y despus
volver a donde nos quedamos con el motor.
3) Un SO nos ayuda a disear ms rpido sistemas mas complejos.
Imagnense ahora una aplicacin donde tengamos que hacer clculos, encender y
apagar cosas, comunicarnos con otros dispositivos y otras tareas ms, y que adems
tengamos que hacerlo rpido y trabajando con otras personas. Entonces el concepto de
divide y vencers nos pude ser til y un SO es el arma que podemos utilizar para
derrotar a nuestros enemigos: el tiempo y la complejidad. Pues s nos auxiliamos del
SO para dividir y gestionar los procesos, y con ello no eliminamos la complejidad pero
le damos una vuelta elegante, y no matamos al tiempo pero le damos menos
oportunidad de que sea l el que nos mate y si no que el jefe nos bote.
4) Un SO nos puede ayudar a hacer sistemas ms estables.
Ahora tenemos unas rutinas que demoran cierto tiempo en hacer unos clculos y como
somos listos, hemos activado el WatchDog (WD) para que si la cosa se cuelga en el
campo se reinicie el sistema. Pero que pasa si la rutina demora ms de lo debido y el
WatchDog nos reinicia sin que haya ningn problema real?. Otra vez la gestin de
recursos nos puede ayudar en eso, ya que si nuestra tarea demora ms de lo debido el
SO puede quitarle el procesador para atender al WatchDog y darle el procesador a otra
tarea que tambin lo necesita por algn tiempo. Este caso tambin sirve cuando an
sin el WD ponemos una llamada a una funcin que se queda esperando
indefinidamente por que ocurra algo que no ocurre y el cdigo que le sigue no se
ejecuta en los tiempos establecidos.
Bueno amigos, hasta aqu hemos visto algunas de las cosas en que puede ayudarnos
un SO, y sera maravilloso poder contar con esas herramientas para programar
nuestros PIC. Ms adelante seguiremos aprendiendo un poco sobre la teora de los SO,
para despus meterle el cuerpo a los programas.
Hay algunos libros interesantes sobre los SO, les recomiendo uno que puede ayudarles
mucho en esta primera parte: Sistemas Operativos Diseo e Implementacin. Andrew

S. Tanenbaum.
[Volver al ndice]

> Diferencias entre usar un SO o usar las libreras del compilador de turno.
Nocturno, un integrante del foro, le plantea a Reinier la siguiente pregunta, que es
aprovechada para avanzar en la explicacin de los SO:
"Por lo que leo en el captulo 1 de tu artculo, no veo diferencias entre usar un SO o
usar las libreras del lenguaje que ests utilizando en cada momento. No me cabe duda
que un SO tendr muchas ms aportaciones que las libreras, pero cul es la principal
ventaja que los diferencia?"
Desde el punto de vista de la programacin no ests haciendo otra cosa que utilizar las
libreras del lenguaje u otras creadas por t o por un buen amigo que te las haya
cedido. De hecho si revisamos, por ejemplo, el RTOS de CCS y las funciones que brinda
el lenguaje para desarrollar aplicaciones utilizando esta potencialidad del lenguaje, nos
damos cuenta, que por ejemplo, la directiva #use RTOS lo que hace es indicarle al
compilador que ponga en el programa final, creado por el compilador, el cdigo del
dispatcher (luego vamos a ver que es) del RTOS, y luego nos ofrece unas funciones de
librera como por ejemplo RTOS_WAIT( ), RTOS_ENABLE( ), RTOS_RUN( ), etc, que
nos ayudan a gestionar nuestras tareas (tambin veremos el concepto y la
implementacin en el futuro). Bien hasta ahora nada nuevo, ninguna ventaja, y una
desventaja: consumo de memoria de programa para el dispatcher y complicaciones de
la vida del programador.
Sin embargo la ventaja del SO radica en que le permite al programador contar con una
herramienta para gestionar varias cosas fundamentales en el sistema: el procesador, la
memoria, y los perifricos, en nuestro caso eso sera todo nuestro flamante PIC. De
todos ellos el ms importante es el procesador, ya que es quin hace la mayor parte
del trabajo, el objetivo de nuestro SO es mantener ocupado al procesador con trabajo
til, por ejemplo una demora por SW es hacer trabajar al procesador con trabajo intil
y ese tiempo que se la pasa saltando de aqu para all lo podemos utilizar en hacer
otras cosas y la memoria de programas tambin, despus veremos como hacer eso.
Supongamos ahora que estamos atendiendo un teclado, que no est conectado a
ninguna fuente de interrupcin, no queda ms remedio que encuestar a nuestro
teclado para saber si han oprimido o soltado una tecla, si es as, entonces tenemos que
hacernos cargo de los rebotes, etc. Hay muchas formas de hacer eso, una de ellas
sera:
1-Espera que se oprima o suelte una tecla
2-Espera un tiempo a que termine el rebote
3-Lee el teclado
4-Procesa la tecla
5-Hacer algo con el cdigo del teclado
6-Regresa al punto 1
Pero una forma sencilla utilizando un SO tendra la siguiente forma:

1-Espera que se oprima o suelte una tecla


2-Me dormir hasta que termine el rebote
3-Lee el teclado
4-Procesa la tecla
5-Manda un mensaje (el cdigo del teclado) a la funcin adecuada
6-Regresa al punto 1.
Ahora vemos que la cosa cambi ligeramente porque le hemos dicho a alguien, me voy
a dormir un tiempo, despirtame cuando pase ese tiempo, y cuando tengo el dato o
cdigo de la tecla, le mando un mensaje a alguien (una funcin), no llamo
directamente a la funcin, pongo el dato en algn lugar e indico que hay un dato, es
asunto de ese alguien tomarlo, procesarlo y notificarlo. Esas dos acciones las hago
sirvindome del SO y le dejo a l el problema de despertarme, y poner el mensaje
donde corresponde, sin embargo en este problema el SO puede hacer algo ms que en
principio no est bajo nuestro control.
Como vemos nuestro programa se queda siempre haciendo lo mismo en un lazo
infinito, entonces podemos decirle al SO: "Oye, este cdigo debe ejecutarse todo en tal
tiempo". Entonces, cuando se cumpla el plazo establecido, el SO le quita el procesador
a ese que se lo quiere coger todo para l solo y se lo da a otra funcin que hace algo
parecido o para que se atienda una interrupcin, etc. cuando todo el mundo haya
recibido su poco de tiempo de procesador, le dice a la funcin que atiende el teclado:
toma el procesador por el tiempo que te corresponde y as todo el mundo puede tener
el procesador para el solo durante un tiempo, es decir ponemos a un vigilante a que
reparta equitativamente el tiempo del procesador.
Hasta aqu hemos visto algunas de las ventajas, ms adelante veremos muchas ms,
sin embargo todava no hemos terminado con la introduccin terica a los SO, pero
para los ms aventajados esto puede aclarar algunas de sus dudas. Yo se que cosas
como esta se pueden hacer blandiendo interrupciones a derecha e izquierda, y con
otras tcnicas, pero como veremos ms adelante los SO nos ayudan en otras cosas,
mientras aprovechamos al mximo nuestros preciados recursos del PIC.
[Volver al ndice]

> Qu es un Sistema Operativo?


Segn Tanenbaum, una de las personalidades ms reconocidas en el mundo acadmico
de los SO, no es fcil dar una definicin definitiva de lo que es un SO. El problema
consiste en que los SO tienen la caracterstica de comportarse para el usuario (que
puede ser una persona cualquiera, un programador, o un programa de computadora),
como un tipo con "doble personalidad".
Veamos esto con ms detenimiento:
1) El SO como mquina extendida:
En esta faceta de la personalidad del SO, la caracterstica destacable es simplificar al
programador los detalles del funcionamiento de los dispositivos conectados al sistema.
Esta caracterstica se pone tambin de manifiesto en aplicaciones donde no se usan los
SO, un ejemplo tpico son las funciones output_x() e input_x() del compilador CCS.
Un programador puede utilizar estas funciones sin conocer que para que los datos se
pongan en los pines o se lean, hay que cambiar varios registros en el uC. Se dice que

estas funciones son una abstraccin del proceso de E/S en puerto. Esto es bueno
porque ayuda a los programadores a desarrollar soluciones ms rpidamente y con
menor probabilidad de errores ya que si la funcin est bien escrita es poco probable
que falle.
La funcin de la mquina extendida es ofrecer al programador una "interfaz" gracias a
la cual se utilizan los recursos del sistema, sin tener que profundizar demasiado en los
detalles del funcionamiento de sus diferentes componentes. Esta interfaz que el SO
ofrece al programador o el usuario, se conoce comnmente como Llamadas al Sistema
o API (Aplication Programmer Interface).
Sin embargo esta visin de los sistemas operativos es poco aplicable a nuestro
entorno, en el sentido en que hoy se clasifican a las llamadas al sistema, ya que en
nuestro mundo todo es pequeo en cuanto a capacidad y el crear una mquina
extendida poderosa consume recursos que usualmente no tendremos. Entonces en
este caso la mquina extendida queda limitada a algunas llamadas a funciones del SO
y al uso de las libreras que hasta el momento hemos utilizado habitualmente.
2) El SO como administrador de recursos:
En este caso el SO, se comporta como un administrador de nuestros recursos. La
ventaja de tener alguien que administre eficientemente los recursos consiste en que el
SO ofrezca al usuario un conjunto de reglas para compartir y hacer uso de los recursos
disponibles con eficacia y eficiencia.
Un ejemplo de administracin de los recursos es el uso de la CPU, en un sistema sin
SO, el programador tiene que estar muy pendiente de la implementacin de su
sistema, porque puede que determinados requisitos temporales en la ejecucin de
algunas funciones tengan que cumplirse.
En nuestro caso lo usual es que nos rompamos el coco manipulando interrupciones,
poniendo demoras, cambiando contadores y chequeando banderas Uf solo de
pensarlo me dan ganas de llorar! Sin embargo un SO puede hacerse cargo de todos
esos temas de manera eficaz y eficiente, incluso ahorrando memoria y tiempo, y
nosotros los programadores concentrarnos en la implementacin de la solucin, ms
que en la gestin eficiente de nuestros recursos.
Por supuesto que el SO no es mago ni adivino, para ello debe ofrecernos un conjunto
de mecanismos, relativamente sencillos, que nos ayuden a "indicarle" o "pedirle" que
es lo que queremos hacer.
En el caso de los uC, las implementaciones de los SO, se caracterizan por potenciar la
administracin de recursos del SO, por lo que es esta la faceta de personalidad que
ms a menudo encontraremos en los RTOS.
[Volver al ndice]
> Clasificacin de los SO.:
A continuacin veremos como se clasifican los SO en cuanto a dos caractersticas
esenciales: la administracin del recurso fundamental (el procesador) y el destino del
SO.
Los SO se pueden clasificar de distintas maneras, pero para abreviar lo ms posible,

solamente me voy a referir a las ya mencionadas.


En cuanto a la administracin del procesador existen dos clasificaciones:
1) SO cooperativo (no preemptive):
En este caso es el programador quin tiene la responsabilidad de entregarle el
procesador al ncleo del SO, para que ste lo entregue a la prxima tarea que est
solicitndolo o programada para ejecutarse. Es entonces, muy importante, que las
llamadas a funciones que ejecutemos nunca se queden esperando mucho tiempo por
determinados eventos, evitar los lazos infinitos y entregar el procesador cuando no lo
necesitemos, para que otra tarea o proceso pueda utilizarlo.
2) SO de tiempo compartido (preemptive):
En este caso el programador debe contar con los mismos mecanismos que en el
anterior, pero el SO tiene la facultad de quitarle el procesador y drselo a otro si usted
se ha excedido en su tiempo o hay alguien que tiene mayor prioridad.
En cuanto al destino hay unas cuantas clasificaciones pero me voy a concentrar en los
RTOS. Un RTOS (Sistema Operativo de Tiempo Real) es un sistema operativo
concebido para dispositivos pequeos como los uC. Aunque el concepto de "tiempo
real" es muy controversial, la idea es ejecutar determinadas tareas de forma que
parece que cada tarea se est ejecutando en un sistema independiente, donde el
procesador y el resto de los recursos son slo para ella.
Los RTOS pueden ser utilizados tambin para computadoras grandes, pero la idea
sigue siendo la misma, ejecutar las tareas cumpliendo estrictamente con los requisitos
temporales de cada una, sin violaciones de ninguna ndole. Otro caso de SO, son los de
propsito general como UNIX, LINUX, Windows, en este caso a diferencia de los RTOS,
las tareas cambian de prioridades en funcin de satisfacer las exigencias de los
humanos que actan como usuarios, no importa si algunas cosas se ejecutan o no
cumpliendo tiempos estrictos.
En la prxima entrega ya tendremos cdigo para ejecutar y ver como funciona un
RTOS.
[Volver al ndice]
> Introduccin al RTOS de CCS
Despus de teorizar un poco sobre los Sistemas Operativos, vamos a introducirnos en
la programacin de aplicaciones empleando un RTOS.
En nuestro caso, para comenzar, utilizaremos el RTOS que viene con el compilador de
CCS. Las razones de mi eleccin las expongo a continuacin:
-

Sencillez en la implementacin de aplicaciones.


El RTOS est integrado en el propio compilador de CCS.
Abundante experiencia en el foro con este compilador.
Gran cantidad de dispositivos soportados por el compilador de CCS.

La versin del compilador que tengo instalada en estos momentos es la 3.249, as que
si en versiones posteriores han aparecido nuevas caractersticas, les ruego que lo
informen para tomar las debidas providencias en el momento oportuno, y comenzar a
utilizar esas nuevas caractersticas.

El RTOS de CCS es un Sistema Operativo de Tiempo Real que implementa la tcnica de


multiprocesamiento cooperativo (non preemptive), por lo que es responsabilidad del
programador asegurarse de que el control del procesador retorna al planificador de
tareas en algn momento. As que cuando programemos nuestra aplicacin, tenemos
que asegurarnos de que no llamamos a una funcin que se queda esperando por algn
evento largo como es el caso de gets(), o dentro de un lazo infinito o demasiado
extenso.
Planificador de tareas
Uno de los elementos fundamentales de cualquier SO es el planificador de tareas, ste
seor es el administrador de nuestros recursos. Su misin fundamental es determinar
dentro de las tareas que estn listas para ejecutarse, a cul de ellas le entrega el
procesador. La poltica de planificacin empleada por CCS no la conozco, pero eso no
importa porque el RTOS funciona y para lo que queremos hacer, nos sirve bien.
Directivas del preprocesador
Existen dos directivas del preprocesador para el uso del RTOS, ellas son:
#USE RTOS: Se utiliza para indicarle al compilador que se va a utilizar el RTOS
#TASK: Se utiliza para indicarle al compilador se la funcin definida a continuacin es
una tarea a ejecutar por el RTOS
Vamos a ver ms detenidamente cada una de las directivas, as como sus parmetros
de configuracin:
#USE RTOS : Opciones del RTOS:
timer: especifica que temporizador, de los disponibles, es el que se utilizar para la
ejecucin de las tareas. Este temporizador solamente debe ser utilizado por el RTOS y
tpicamente se escoge Timer0.
minor_cycle: especifica la cantidad de tiempo mnima que una tarea tendr para
ejecutarse, y los tiempos de ejecucin de cada tarea deben ser mltiplos de esta
cantidad. Si por ejemplo decimos que el tiempo mnimo de ejecucin para todas las
tareas es de 1ms, debemos conocer que cada tarea se ejecutar, en menos tiempo
que este. Lo realmente importante de este dato es que ayuda a establecer la
frecuencia con que se ejecutan las tareas, luego veremos un ejemplo de esto. Este
parmetro, si no se especifica, es calculado por el compilador en el momento de la
compilacin.
statistics: le indica al compilador que lleve las estadsticas de las tareas, esto sirve
para conocer que tiempo consume cada tarea en ejecutarse, sin embargo como
veremos ms adelante, la estadstica realmente importante es la que nos indica si
nuestra tarea se ha sobrepasado en su tiempo mnimo de ejecucin.
#TASK: Opciones para las tareas:
rate: especifica con que frecuencia se ejecuta la tarea, este parmetro debe ser igual a
minor_cycle de #use_rtos o un mltiplo de este valor.
max: especifica que cantidad de tiempo debe consumir esta tarea en su ejecucin, si
se sobrepasa este tiempo y estn activadas las estadsticas, entonces esta tarea es

marcada con el valor overrun. Este parmetro es til para informar al programador que
una tarea se ha pasado de su tiempo de ejecucin, y si el RTOS fuera de tiempo
compartido seguramente especificara el tiempo en que el planificador le retira el
procesador para drselo a otra tarea.
queue: especifica el tamao de la cola de mensajes de la tarea. Si la tarea no recibe
mensajes, entonces debe dejarse en blanco para no consumir memoria RAM
innecesariamente.
Hasta aqu hemos visto una pequea explicacin de las directivas para utilizar el RTOS.
Sin embargo, la utilidad de esto es mejor verla con un ejemplo.
[Volver al ndice]
> Funciones del RTOS
EL RTOS de CCS ofrece un conjunto de funciones que veremos cada una en su
momento y con sus debidos ejemplos. Sin embargo hoy utilizaremos solamente la
funcin rtos_run(), que le indica al planificador que comience a ejecutar las tareas.
El ejemplo:
Se quiere implementar una aplicacin en un PIC16F877, donde se utilice el RTOS para
transmitir por el puerto serie de este uC, tres cadenas de caracteres. Cada cadena ser
transmitida desde dentro de una tarea del RTOS y tendrn el formato Ejecutada tarea
#. Las especificaciones de tiempo del sistema y de cada tarea son las siguientes:
Temporizador para el RTOS: Timer0
Tiempo mnimo en que debe ejecutarse una tarea: 10ms
Frecuencia de ejecucin de la Tarea 1: 1seg, tiempo para ejecutar: 10ms
Frecuencia de ejecucin de la Tarea 2: 2seg, tiempo para ejecutar: 5ms
Frecuencia de ejecucin de la Tarea 3: 3seg, tiempo para ejecutar: 250us
El cdigo lo pongo a continuacin y posteriormente les doy una explicacin:
Cdigo:
#include "D:\Documentos\Projects\RTOS\RTOS.h"
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=9)
#use RTOS(timer=0, minor_cycle=10ms) //temporizador Timer0, tiempo mnimo de ejecucin
de cada tarea 10ms
int8 test;
//Definicin de las prototipos de funcin de las tareas
#task (rate=1s, max=10ms) //Ejecutar cada 1 segundo y consumir como mximo 10ms
void Tarea1();
#task (rate=2s, max=5ms) //Ejecutar cada 2 segundos y consumir como mximo 5ms
void Tarea2();
#task (rate=3s, max=250us) //Ejecutar cada 3 segundo y consumir como mximo 250us
void Tarea3();
void main()
{
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
rtos_run(); //A partir de aqu comenzar la ejecucin de las tareas

}
//Implementacin de las tareas
void Tarea1()
{
printf("Ejecutada tarea 1\r");
}
void Tarea2()
{
printf("Ejecutada tarea 2\r");
}
void Tarea3()
{
printf("Ejecutada tarea 3\r");
}
Este cdigo funciona y si lo simulan con el Proteus comprobarn que las cadenas salen
por el puerto serie. Como pueden ver es un ejemplo sencillo pero que muestra el
funcionamiento del RTOS. Al ejecutarlo pueden comprobar que primero se ejecuta la
Tarea 1, pero despus comprobarn que las tareas no se ejecutan en orden secuencial
porque la Tarea 2 se ejecutar cada 2 segundos y la Tarea 3 cada 3 segundos.
La no ejecucin secuencial de cada tarea se debe al parmetro rate de la directiva
#task, que le dice al planificador con que frecuencia ejecutar cada tarea. Este
programa puede ser fcilmente modificado para cualquier aplicacin especfica, un
ejemplo que se me ocurre es la lectura de teclados y eliminacin de rebotes.
[Volver al ndice]

> Controlando la ejecucin de las tareas


En la pasada entrega sobre programacin con el RTOS de CCS vimos como es que el
planificador programaba la ejecucin de las tareas que estaban activas para ser
ejecutadas. Pero como es lgico en todo momento las tareas no tienen por que
encontrarse en condiciones de ser ejecutadas, a veces hace falta poner a dormir una
tarea y despertarla cuando hace falta que se ejecute.
Para lograr este objetivo el RTOS de CCS nos ofrece dos funciones:
RTOS_DISABLE( ) y RTOS_ENABLE( )
Al crear una tarea el RTOS la marca como activa (enable), y cuando comienza a
ejecutarse el planificador de tareas la pondr en la cola de ejecucin para ejecutarla
cuando le llega su turno. Sin embargo en muchas ocasiones notaremos que no hace
falta ejecutar la tarea hasta que se cumplan ciertas condiciones.
Este es un mecanismo simple, que sin el uso del RTOS controlaramos mediante una
bandera (flag), y la implementacin de una funcin a la cual llamaremos si se cumple
la condicin de su ejecucin.
Hasta el momento el RTOS no nos ofrece ninguna ventaja respecto al mtodo
tradicional, sin embargo combinemos esta caracterstica con lo aprendido en el ejemplo

de la entrega anterior y comprobaremos que si hay ventajas, y por cierto nada


despreciables.
La ventaja principal con respecto al mtodo tradicional consiste en que usted hace la
consulta para comprobar si hay que ejecutar la funcin, sin embargo ahora solamente
le dice al RTOS, habilita a la tarea tal y ponla a ejecutarse cuando le corresponda y se
olvida de todos los problemas asociados respecto al tema de cuando le corresponde
ejecutarse la tarea y dems.
Alguien se acuerda de los molestos temporizadores, banderas, registros y Dios sabe
cuantos engendros de control de ejecucin condicional para una funcin estndar?
De forma similar a como se le dice al planificador que la tarea tal debe ser ejecutada,
podemos avisarle para que no la ejecute.
Veamos esto con un ejemplo:
Tenemos una aplicacin en la que hemos colocado tres LEDs uno rojo en RB0, uno
verde en RB1 y otro amarillo en RB2. Vamos a encender y apagar los LEDs con una
frecuencia determinada y a intervalos regulares segn el siguiente esquema:
- Led Rojo parpadea con una frecuencia de 250ms por un perodo de 5s, el resto
apagado.
- Led Verde parpadea con una frecuencia de 350ms por un perodo de 10s, el resto
apagado.
- Led Amarillo parpadea con una frecuencia de 450ms por un perodo de 15s, el resto
apagado.
- Todos los LED parpadean, cada uno con su frecuencia correspondiente durante 5s.
- Comenzamos por el LED rojo nuevamente y repetimos el ciclo.
La solucin que les propongo es la siguiente:
- 3 tareas para controlar el parpadeo de cada LED y el tiempo que se ejecutan
- 1 tarea para controlar el tiempo en que todos los LEDs parpadean.
Tenemos un total de 4 tareas en la aplicacin y el control de la ejecucin ser el
siguiente:
Al inicio solamente la tarea LED_R estar habilitada, una vez que LED_R ha concluido
inicia la tarea LED_V y se autodeshabilita.
Cuando LED_V concluye habilita LED_A y se autodeshabilita.
Cuando LED_V concluye habilita LEDS y se autodeshabilita.
Cuando LEDS se inicia por primera vez habilita LED_R, LED_V y LED_A cuando le toca
de nuevo el turno se autodeshabilita y deshabilita a LED_V y LED_A
Veamos el cdigo:
Cdigo:
#include "D:\Documentos\Projects\RTOS\RTOS.h"
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=9)
//Como el reloj de este micro se ha puesto a correr con 20MHz el Timer0 no tiene
//mayor resolucin que 10ms, es por eso que el tiempo mnimo de ejecucin es de 10ms
#use RTOS(timer=0, minor_cycle=10ms)

int1
int1
int8
int8
int8
int8

iB0, iB1, iB2;


iLEDS = 0;
iCountR = 0;
iCountV = 0;
iCountA = 0;
iCount = 0;

#task (rate=10ms, max=10ms)


void Task_Disabler();
#task (rate=250ms, max=10ms)
void LED_R();
#task (rate=350ms, max=10ms)
void LED_V();
#task (rate=450ms, max=10ms)
void LED_A();
#task (rate=5s, max=10ms)
void LEDS();
void main()
{
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
rtos_run();
}
//esta es una funcin truculenta porque las tareas no pueden crearse deshabilitadas
//y no se pueden deshabilitar hasta que el RTOS est funcionando. Lo considero una
//deficiencia sustancial de este RTOS
void Task_Disabler()
{
rtos_disable(LED_V);
rtos_disable(LED_A);
rtos_disable(LEDS);
rtos_disable(Task_Disabler);
}
//cada tarea tiene un contador para llevar la cantidad de veces que se pasa por la
//funcin y cuando se cumple el tiempo establecido entonces habilita y deshabilita
//las tareas correspondientes
void LED_R()
{
iB0 = !iB0;
output_bit( PIN_B0,
if (iCountR++==20)
{
iCountR = 0;
rtos_disable(LED_R);
rtos_enable(LED_V);
}
}
void LED_V()
{
iB1 = !iB1;

iB0);

output_bit( PIN_B1,
if (iCountV++==27)

iB1);

{
iCountV = 0;
rtos_disable(LED_V);
rtos_enable(LED_A);
}
}
void LED_A()
{
iB2 = !iB2;
output_bit( PIN_B2,
if (iCountA++==33)
{
iCountA = 0;
rtos_disable(LED_A);
rtos_enable(LEDS);
}
}

iB2);

void LEDS()
{
if(!iLEDS)
{
rtos_enable(LED_R);
rtos_enable(LED_V);
rtos_enable(LED_A);
iLEDS = 1;
}
else
{
rtos_disable(LED_V); //Hay que habilitar y deshabilitar explcitamente
rtos_disable(LED_A); //cada tarea sobre todo LED_R que debe continuar
rtos_disable(LEDS); //ejecutndose otros 5 segundos ms
rtos_enable(LED_R);
iCountR = 0;
iCountV = 0;
iCountA = 0;
iLEDS = 0;
}
}

Cuando corran y simulen el ejemplo vern que a veces los LEDs se quedan encendidos
o apagados indistintamente, este es un problema del programa, ya que lo deseable
sera que los LEDs se quedaran apagados cuando termina la funcin. Sin embargo lo
he dejado as porque en el futuro vamos a ver cmo podemos hacer esto con las
propias funciones del RTOS.
Como la vez anterior, les dejo de tarea hacerlo sin RTOS para ver como les queda, a mi
llev menos de dos horas elaborar el texto y escribir el cdigo. Me imagino que sin
RTOS me tardara ms de un da completo, consumira un montn de pginas de
explicacin y otro montn para el cdigo.
Este es un mtodo simple, pero hay otros mucho ms elaborados que iremos viendo
poco a poco. La prxima entrega ser yield() vs delay(), vamos a ver el mtodo de

las esperas eficientes.


[Volver al ndice]

> Yield vs delay


Cuantas veces en nuestras aplicaciones tenemos que situar demoras para esperar la
ocurrencia de un evento determinado? Por ejemplo, para eliminar rebotes en un
teclado, esperar a que el conversor AD termine y quin sabe cuantas cosas ms.
Normalmente estas demoras se hacen poniendo al procesador a decrementar
contadores y dar saltos recursivos como si fuese un loco. Durante todo el tiempo de la
demora, nuestro microcontrolador, estar ocupado en perder el tiempo, y es por eso
que a este mecanismo se le llama espera ocupada.
Sin embargo un RTOS nos ofrece un conjunto de herramientas para eliminar este
molesto inconveniente, el ms sencillo de ellos es aquel que le permite a una tarea
decirle al RTOS: ponme a dormir hasta que me toque de nuevo mi turno de
ejecutarme. Para ese efecto el RTOS de CCS implementa la funcin rtos_yield().
Este mecanismo es muy bueno puesto que mientras la tarea se duerme nuestro
microcontrolador puede dedicarse a realizar otras tareas tiles y hacer de la espera
ocupada una espera eficiente. Para la tarea que est dormida esto no representa nada,
a ella le da lo mismo ocupar al procesador en hacer nada que en hacer algo productivo,
sin embargo no ocurre lo mismo para el resto de las tareas que estn esperando que
se les entregue el procesador.
Otro caso en que yield() nos puede ser til es para entregar el procesador cuando nos
hemos pasado de tiempo en la ejecucin de alguna tarea. Ya sabemos que el RTOS de
CCS es cooperativo, por lo que si una tarea consume ms tiempo de la cuenta puede
hacer que el sistema colapse, ya que hay que entregar explcitamente el procesador al
RTOS para que se lo de a otra tarea.
Sin embargo con la funcin de las estadsticas habilitadas, podemos comprobar si
alguna tarea se ha pasado de tiempo, y con ello implementar mecanismos adecuados
para que la tarea en cuestin reajuste su dinmica y ceda el procesador
oportunamente, para ello podemos auxiliarnos de la funcin rtos_overrun(). Esta
funcin no tiene valor si se usa dentro de una tarea para comprobar si ella misma se
ha pasado porque la actualizacin de las estadsticas se hace despus de ceder el
procesador, considero que esta es una de las debilidades de este RTOS, en ese sentido.
El uso de rtos_overrun(), debera poderse utilizar dentro de una misma tarea para
comprobar si desde que me cedieron el procesador para ejecutar, me he pasado de
tiempo o no y en consecuencia entregar el procesador al RTOS.
En el ejemplo que les traigo hoy vamos a emplear rtos_yield() para ceder el
procesador y rtos_overrun() para conocer si una tarea se ha pasado de tiempo.
Sin embargo yield() no es una funcin realmente poderosa, al menos en este RTOS,
porque pone a dormir a la tarea durante un perodo completo del valor rate, que
especificamos al declarar la funcin como una tarea del RTOS, y eso en ocasiones no
es lo que deseamos. An as es mejor que el procesador de nuestro PIC est haciendo
algo til y no perdiendo el tiempo.

En las entregas futuras veremos otras funciones que nos ofrece este RTOS para hacer
esperas ms eficientes vinculadas al uso de recursos compartidos en nuestras
aplicaciones. El uso eficiente del procesador, los recursos del sistema y la no linealidad
en la ejecucin de las tareas en un sistema que emplea SO, ha obligado a los
diseadores de SO a crear mecanismos para proteger los datos y hacer uso de esos
recursos de forma ordenada y segura. Estos mecanismos se clasifican en dos grupos:
La sincronizacin y la coordinacin que comenzaremos a ver en la prxima entrega.
Ejemplo:
Implemente en un PIC16F877 una aplicacin en la que se ejecuten tres tareas, con las
siguientes caractersticas:
- La tarea No. 1 Tendr un contador el cual se incrementa en un lazo hasta que alcanza
el valor de 1000. Cuando llegue a ese valor imprime el siguiente mensaje: Tarea
contadora completada y adems pone una bandera a 1, para indicar que ha concluido.
Debe colocar en esta tarea cdigo para que la tarea ceda el procesador en algn
momento al RTOS. El tiempo mximo de ejecucin de esta tarea es de 10ms y debe
ejecutarse cada 30ms.
- La tarea No. 2 debe esperar a que la tarea No. 1 termine para enviar por el puerto
serie un mensaje similar al de la tarea No. 1, sin embargo, esta tarea tambin enviar,
por el puerto serie, un mensaje cada vez que le cede el procesador al RTOS. Esta debe
ejecutarse en un tiempo de 10ms y debe ejecutarse cada 40ms.
- Por ltimo, existe una tarea que se encarga de hacer parpadear un LED conectado en
RB0, cada 100ms y enviar un menaje por el puerto serie en caso de que la Tarea 1 o la
Tarea 2 se hayan pasado en algn momento de su tiempo de ejecucin. El tiempo de
procesador para esta tarea debe ser de 10ms.
Cdigo:
#include "D:\Documentos\Projects\RTOS\RTOS.h"
#use rs232(baud=19200,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=9)
#use RTOS(timer=0, minor_cycle=10ms, statistics) //se utilizan las estadsticas
//hace falta para usar rtos_overrun()
int32 iT1Counter = 0;
int1 bT1Flag = 0;
int1 bLed = 0;
#task (rate=30ms, max=10ms)
void Tarea1();
#task (rate=40ms, max=10ms)
void tarea2();
#task (rate=100ms, max=10ms)
void Tarea3();
void main()
{
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
rtos_run();
}

void Tarea1()
{
bT1Flag = 0;
for(iT1Counter = 0; iT1Counter <= 1000; iT1Counter++)
{ if(!(iT1Counter%100)) //mecanismo para ceder el procesador cada cierto tiempo
rtos_yield(); //cuando la tarea entra en contexto se comienza a ejecutar
//la lnea a continuacin de esta
}
printf("Tarea contadora completada\r");
bT1Flag = 1;
}
void tarea2()
{
//Aunque esta tarea no tiene que preocuparse mucho por ceder el procesador
//porque no tiene lazos infinitos o algo parecido puse de ejemplo tambien a
//rtos yield
if(bT1Flag)
printf("Espera por Tarea1 concluida\r");
else
{
printf("dormir T2\r");
rtos_yield();
}
}
void Tarea3()
{
bLed = !bLed;
output_bit( PIN_B0, bLed);
if(rtos_overrun(Tarea1)) //Si las tareas se pasaron de su tiempo de ejecucin
//se envan los mensajes por el pto serie
printf("Tarea 1 overrun\r");
if(rtos_overrun(Tarea2))
printf("Tarea 2 overrun\r");
}
Como pueden observar, este ejemplo realmente no se corresponde con una aplicacin
que haga algo til, sin embargo, me ha servido para ilustrar el uso de las funciones
rtos_yield() y rtos_overrun() de la manera ms sencilla que encontr. Las
posibilidades de estas funciones estn ahora en sus manos y en lo que sus cabezas
puedan crear para ellas. Hay muchsimas aplicaciones en las que pueden ser tiles, sin
embargo, ya el tema de los RTOS es bastante complicado como para meternos a hacer
programas complejos que demuestren su uso.
El tiempo invertido para hacer el cdigo y el texto, fue de 2:30 hrs, la decisin de que
ejemplo utilizar me tom ms de un da.
[Volver al ndice]

> Coordinar para no daar

Hasta ahora hemos visto al RTOS como un elemento que nos ayuda a simplificar el
cdigo de nuestra aplicacin. Por una parte, dejndole parte de la temporizacin de las
tareas que debe realizar nuestra aplicacin y por otra utilizando el tiempo de las
demoras ocupadas para hacer que otras tareas ejecuten su cdigo en ese tiempo. Sin
embargo esas ventajas no son nada comparado con dos herramientas fundamentales
que nos ofrecen los SO: la coordinacin y la sincronizacin, de ellas hoy vamos a ver
solamente una de ellas: la coordinacin.
La coordinacin es un trmino en la programacin para SO, que se basa en la
proteccin de recursos compartidos, es un concepto orientado a evitar que diferentes
tareas puedan acceder a los datos o recursos y poner al sistema en un estado inestable
o inseguro.
Ejemplos que ponen de manifiesto el problema de la coordinacin hay muchsimos pero
en aras de mantener el curso lo ms sencillo posible y adecuarlo un poco ms a las
aplicaciones que normalmente se nos presentan yo utilizar un problema ms cercano
a nuestro entorno.
El problemas de la coordinacin tambin se conoce como el problema de la
concurrencia o acceso concurrente a recursos, a mi me gusta llamarlo coordinacin
para establecer una mejor diferencia con respecto al otro mecanismo; el de la
sincronizacin que veremos en la prxima entrega.
Destripando un poco ms a la coordinacin diremos que: "la coordinacin es el
mecanismo que debe implementar un SO para asegurar el acceso seguro a recursos
compartidos del sistema, y que no tiene en cuenta restricciones temporales". Con esto
queda claro que proteger a los recursos de un acceso no seguro es lo ms importante
en la coordinacin, no importa durante que tiempo alguien (una tarea) est utilizando
el recurso, hasta que no lo libere nadie ms podr utilizarlo.
Hay mecanismos de coordinacin que implementan tambin el problema de la
sincronizacin, que si tiene en cuenta el factor tiempo, pero el RTOS de CCS no los
implementa. Esto puede considerarse una limitante o una ventaja, segn el tipo de
aplicacin en que se vaya a utilizar.
Un RTOS que implementa un mecanismo de coordinacin con sincronizacin es el
LMOS de Darukur, que veremos dentro de algn tiempo en este foro, debidamente
documentado gracias a un proyecto que Darukur y un servidor, llevaremos a ustedes.
Por el momento este simple cursillo es un buen mtodo (no el nico) para acercarse al
mundo de los RTOS.
Veamos la coordinacin con un ejemplo sencillo pero bien claro:
"Supongamos que una madre ha comprado una camisa muy bonita, ella quera
comprar dos, pero en la tienda solo haba una as que decidi comprarla de todas
formas. Cuando lleg a casa llama a sus hijos (ambos usan la misma talla de camisa),
y les dice: he comprado esta camisa, pero en la tienda solamente haba una, as que
deben compartirla como buenos hermanos.
Las palabras de la madre no son alentadoras porque a ambos les gusta mucho la
camisa y sin embargo deben compartirla, entonces la decisin de ambos es colocar la
camisa en una percha, y cada vez que uno de los dos decida utilizarla se la ponga
(dejando el perchero vaco). Pero hay una regla adicional, si cuando uno de los dos va

a utilizar la camisa el otro ya se la llev dejar una marca para indicarle al otro
hermano que no podr utilizar la camisa hasta que el que la marc haya hecho uso de
ella."
Este es un mecanismo en que los hermanos se han puesto de acuerdo para utilizar un
recurso (la camisa), de manera compartida (porque es la nica), de forma coordinada
(para eso se pusieron de acuerdo e hicieron unas reglas simples).
Para implementar las reglas mostradas en el ejemplo anterior, el RTOS de CCS tiene
dos funciones rtos_wait() y rtos_signal().
Para utilizar estas funciones primero hay que crear una variable entera que har las
funciones de percha y, que hablando con propiedad, se llama semforo. El semforo es
el elemento que le permite a la tarea reclamar el recurso compartido o esperar por l
si ya est en uso. Las funciones rtos_wait() y rtos_signal() se utilizan para marcar el
momento de inicio y fin del cdigo que utiliza el recurso compartido. A la seccin de
cdigo que utiliza el recurso compartido se le conoce como seccin crtica.
Veamos como funciona esto en trminos de programacin:
Usted crea una variable entera que ser su semforo o marcador de uso del recurso
compartido.
El recurso compartido puede ser una o varias variables del sistema, en este caso el
recurso compartido es un recurso de memoria. O puede ser un perifrico del sistema,
como es el caso del puerto serie o la memoria EEPROM, o cualquier otro.
rtos_wait() y rtos_signal() son los marcadores de inicio y fin del cdigo que hace uso
de nuestro recurso compartido.
Cuando se inicia el programa usted inicializa el semforo en algn valor positivo que
determina la cantidad de tareas que pueden utilizar el recurso al mismo tiempo,
normalmente es uno para las tareas que modificarn el recurso compartido, mientras
que para tareas que solamente leen datos puede que no se usen secciones crticas o se
permita ms de una tarea que acceda simultneamente al recurso compartido.
Cuando una tarea llegue a la seccin de cdigo que hace uso del recurso compartido,
debe, primero que nada, ejecutar la funcin rtos_wait(sem). Si el semforo es mayor
que cero, el RTOS decrementar la variable y permitir que la tarea contine su
ejecucin, sin embargo si el semforo est en cero, el RTOS le quitar el procesador a
la tarea y se lo ceder a otra que le toque ejecutarse. Cuando le corresponda
nuevamente a la tarea que pidi el acceso al recurso compartido, el RTOS comprobar
el estado del semforo, si ste es mayor que cero, lo decrementar y le dar el
procesador a la tarea para que se siga ejecutando, si no, volver a dormir a la tarea
hasta el prximo turno y as sucesivamente.
Al final del cdigo de la seccin crtica hay que colocar un rtos_signal(sem) para que el
RTOS incremente el semforo permitiendo que otra tarea pueda utilizar el recurso
compartido.
El ejemplo de hoy es el siguiente:
Elabore un programa para un PIC16F877 que permita mantener actualizada la cantidad
de botellas que hay en un tramo de cinta transportadora en una embotelladora. La
cinta es alimentada desde un almacn de botellas que tiene un robot que incrementa la
variable Cantidad cada vez que coloca una botella en la cinta, mientras que dos robots

llenadores de cajas, decrementan en 12 la variable cantidad cada vez que toman 12


botellas de la cinta transportadora.
Como es de suponer el robot despachador debe llenar la cinta ms rpido de lo que los
robots llenadores la vacan.
En la prxima entrega utilizaremos la sincronizacin para resolver el problema de que
la cinta se quede vaca o se llene demasiado rpido. Como datos adicionales suponga
que el robot despachador despacha una botella cada 250ms y que los robots llenadores
llenan una caja cada 6 segundos. El robot despachador est conectado a RB0 y cada
vez que pone una botella en la cinta transportadora le da un pulso al microcontrolador
para indicrselo. Los robots llenadores estn conectados uno a RB1 y el otro a RB2 e
igualmente dan un pulso al microcontrolador cada vez que despachan una caja. La
duracin del pulso es de 100ms.
Como es de suponer este problema lo podemos resolver de muchas maneras y
lgicamente sin el uso de los RTOS, pero eso se los dejo de tarea. Adems el
mecanismo de notificacin de cada robot es un poco deficiente, pero ese no es el tema
de este curso, aunque en su momento pondremos un ejemplo mejor al respecto,
cuando rescatemos a las interrupciones del olvido.
Analicemos un poco en detalle el problema: Supongamos que la tarea asociada al
robot despachador comienza a ejecutarse, lee el valor de la variable Cantidad, 100
botellas, y se va adormir esperando que el robot le notifique que ha puesto una botella
en la cinta, en ese momento el RTOS le da permiso a la tarea del robot llenador 1 para
que ejecute su cdigo, sta se da cuenta que el robot llen una caja por lo que lee la
variable Cantidad y le resta 12 botellas, quedando Cantidad = 88 botellas. Ahora le
toca de nuevo a la tarea del robot despachador ejecutarse y como ya se despach una
botella le suma uno al valor previamente ledo y actualiza la variable Cantidad,
quedando 101 botellas, lo cual es falso.
Este ejemplo puede mejorarse semnticamente y evitarnos el uso de la seccin crtica,
todo ello gracias a que nuestro RTOS es cooperativo y en este caso, mientras la tarea
est ejecutndose tiene todos los recursos para ella sola hasta que entregue el
procesador.
Por lo tanto podemos escribir el cdigo de modo que no haya ningn rtos_yield()
intercalado con el cdigo que accede a un recurso compartido, de esta forma la tarea
se asegura el uso exclusivo del recurso compartido a no ser que aparezcan las
interrupciones en la palestra y las cosa se complique. Sin embargo en un sistema de
tiempo compartido (los hay para PIC, ejemplo de ellos es el FreeRTOS), donde no
sabemos cuando el RTOS nos quitar el procesador el uso de secciones crticas es
OBLIGATORIO, para evitar problemas como los mostrados, y por eso es importante
que dominemos esta tcnica.
Por otro lado el uso de Perifricos puede complicar ms las cosas que el uso simple de
la memoria y puede ocurrir que para ser eficientes estemos obligados a poner un
rtos_yield() dentro del cdigo de la seccin crtica. Moraleja: aprenda a programar con
secciones crticas o no programe con RTOS.
El cdigo:
#include "D:\Documentos\Projects\RTOS\RTOS.h"
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=9)

#use RTOS(timer=0, minor_cycle=10ms)


int8 semaphore; //Este es nuestro semforo
int16 iCantidad; //Esta es la cantidad de botellas en la estera
//constituye nuestro recurso compartido
#task (rate=50ms, max=10ms)
void R_Despachador();
#task (rate=50ms, max=10ms)
void R_Llenador1();
#task (rate=50ms, max=10ms)
void R_Llenador2();
void main()
{
semaphore = 1; //Solo una tarea puede utilizar el recurso cada vez
iCantidad = 100; //Inicializamos esta variable para tener algunas botellas en
//la estera.
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
rtos_run();
}
void R_Despachador()
{
int Botellas;
rtos_wait(semaphore); //Reclamamos el recurso y aqu comienza la secc crtica
Botellas = iCantidad; //Leemos la cantidad de botellas a una variable temporal
if(input(PIN_B0)==1)
{
Botellas++; //Ya sabemos que este cdigo no es eficiente pero
iCantidad = Botellas; //s es didctico y por eso lo he utilizado as.
}
rtos_signal(semaphore); //Liberamos el semforo y aqu se acaba la sec crtica
rtos_yield(); // A dormir por otros 100ms para evitar poner dos veces la misma botella
}
void R_Llenador1()
{
rtos_wait(semaphore);
if(input(PIN_B1)==1)
iCantidad -= 12; //Este s es un cdigo lgico, pero entonces el despachador
//no nos dara problemas aunque nos vayamos a dormir dentro de
//la seccin crtica.
rtos_signal(semaphore);
rtos_yield();
}
void R_Llenador2()
{
rtos_wait(semaphore);
if(input(PIN_B2)==1)
iCantidad -= 12;

rtos_signal(semaphore);
rtos_yield();
}

Este programa lo simul en Proteus poniendo en RB0 una fuente digital de tipo pattern
con los siguientes parmetros:
First Edge at (Secs)=1
Desmarcar el check mark: Equal Mark/Space Timing?
Mark Time (Secs) = 100m
Sapce Time(Secs) = 150m
Marcar el check mark: Continuos Secuence of Pulses
Marcar el check mark: Standard Hig-Low Pulse Train
Para RB1 y RB2 se utiliza una fuente del mismo tipo con los siguientes parrametros
cambiados
Para RB1:
First Edge at (Secs)=5
Mark Time (Secs) = 100m
Sapce Time(Secs) = 5.9
Para RB2:
First Edge at (Secs)=7
Mark Time (Secs) = 100m
Sapce Time(Secs) = 5.9

Simulen y vean como cada vez que se pasa por rtos_wait() y si el semforo es mayor
que cero, se decrementa y se entra en la seccin crtica, si el semforo es 0 entonces
la tarea espera a que est disponible el recurso (semforo>0) para ejecutar el cdigo
de la seccin crtica.
[Volver al ndice]

> En sus marcas, listos, FUERA!


Un momento, un momento, no tan rpido que, hay una salida en falso del corredor del
carril No. 2.
En un caso como el anterior diramos que ha fallado la sincronizacin de los corredores
en el arranque, y la sincronizacin es el tema que vamos a tratar hoy en nuestro
cursillo de los RTOS para uC.
En el mundo de los uC es frecuente la utilizacin de demoras para esperar a que
ocurran ciertos hechos o eventos, para en consecuencia hacer algo. La duracin de
estas demoras puede ser conocida, como en el caso de esperar a que una LCD coloque
los datos en determinados registros antes de enviarle otro dato, o esperar a que la
USART saque un dato que est transmitiendo antes de poder escribir nuevamente en el
registro de transmisin; sin embargo tambin son frecuentes aquellas esperas en las
que no sabemos cuanto podemos demorarnos.
En los casos en que no conocemos cuanto debemos esperar se pueden utilizar las
interrupciones, pero en los uC no tenemos interrupciones ilimitadas ni tampoco existe

una biblioteca de mecanismos de interrupcin disponibles para todos los casos que se
nos presentan. Es por estas razones que muchas veces esperamos a la ocurrencia de
estos eventos haciendo suposiciones y blandiendo demoras.
Para la implementacin de demoras existen varios mecanismos ms o menos
eficientes, sin embargo un SO no nos ofrece este tipo de mecanismos que podemos
llamar un poco primitivos. Para la implementacin de demoras eficientes los SO han
creado los mecanismos de sincronizacin de procesos.
En la entrega anterior vimos la coordinacin, en realidad los autores de los libros ms
reconocidos en el tema de los SO, han llamado a estos mecanismos y al que veremos
hoy, mecanismos de sincronizacin de procesos, pero a mi me gusta distinguir entre
aquellos que se dedican especialmente a implementar esperas eficientes para la
proteccin de recursos, de aquellos que se dedican a implementar esperas eficientes
para eventos por los cuales un proceso debe esperar antes de continuar su ejecucin.
Notemos que en ambos casos la tarea o proceso debe esperar, pero no en todos los
casos la espera tiene la misma naturaleza, en uno esperamos por un recurso fsico al
que queremos acceder y que no est disponible, en el otro esperamos a que se
produzcan ciertos hechos que determinan el estado del sistema.
Vamos a utilizar como referencia el problema anterior para ver el mecanismo de la
sincronizacin en ejecucin. Supongamos ahora que le hemos colocado a nuestros
robots una entrada que cuando est en nivel bajo le indica al robot que no coloque o
extraiga botellas de la cinta transportadora. Con este mecanismo simple vamos a
tratar, por un lado, de evitar que el robot despachador de botellas llene demasiado la
cinta y por el otro que los robots llenadores de cajas traten de llenar las cajas cuando
no hay suficientes botellas en la cinta transportadora. Es decir, vamos sincronizar el
proceso de llenado/vaciado de la cinta transportadora. Las ventajas de esto son
evidentes, por ejemplo: si el robot llenador no tiene botellas que poner en la cinta los
robots llenadores trabajarn hasta que la cantidad de botellas se lo permita; si los
robots llenadores dejan de trabajar, entonces el robot despachador trabajar hasta que
llene la cinta transportadora.
Para lograr lo anterior, vamos a poner que la cantidad mxima de botellas que pueden
estar en la cinta es de 100 y que la cantidad mnima de botellas es 24, por lo que cada
una de las tareas que atiende a los robots deber, adems de llevar la actualizacin del
total de botellas en la cinta, indicarle a los robots que se detengan cuando la cantidad
de botellas en la cinta est fuera del rango especificado. Adems vamos a utilizar el
puerto serie para Tx la cantidad de botellas que hay en la cinta en cada momento.
Las entradas a los robots (salidas de nuestro PIC) las hemos colocado en los pines
RB3..RB5, en RB3 al robot despachador, en RB4 al robot llenador1 y en RB5 al robot
llenador2
Para hacer la sincronizacin de tareas el RTOS de CCS nos ofrece una sola funcin,
aunque parezca poco esta funcin es bien poderosa, vamos a verla con ms
detenimiento. La funcin se llama rtos_await(expr) lo que tienes que pasarle es una
expresin lgica que la funcin evaluar, si esta resulta verdadera entonces continas
la ejecucin normal de tu programa, si te devuelve falso, entonces rtos_await() le
ceder el procesador al RTOS y la tarea quedar bloqueada hasta que exp se cumpla
para entonces continuar en la lnea siguiente a la llamada a la funcin.
Ahora bien, es cierto que esta funcin es poderosa y simple, pero eso implica que

tenemos que saber donde ponerla, ya que si no evaluamos bien nuestras expresiones o
no colocamos la funcin en el lugar adecuado, estaremos sometindonos a riesgos
durante la ejecucin de nuestro cdigo. Por ejemplo puede ocurrir que alguna tarea se
quede bloqueada esperando por siempre a que la expresin lgica se evale de
verdadera y esto nunca ocurra o que la expresin est mal diseada y la tarea no se
bloquee cuando haga falta. Bien todos esos problemas los veremos ms adelante
cuando la seorita Nmesis (diosa griega de la venganza y la fortuna) haga acto de
presencia para echarnos a perder toda la dicha que los RTOS traen al mundo de la
programacin con uC.
Desde aqui puedes descargar el cdigo fuente y la simulacin con Proteus (57Kb,
formato ZIP)
Cuando corran el ejemplo noten como la cantidad de botellas en la cinta va
descendiendo hasta que al llegar a las 24 botellas, despus la cantidad de botellas en
la cinta se mantendr ms o menos sobre las 20 y nunca por debajo de 12. Las
compuertas AND de conjunto con las formas de onda hacen la funcin de los robots.
El cdigo:
#include "D:\Documentos\Projects\RTOS\RTOS.h"
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=9)
#use RTOS(timer=0, minor_cycle=10ms)
int8 semaphore; //Este es nuestro semforo
int16 iCantidad; //Esta es la cantidad de botellas en la estera
//constituye nuestro recurso compartido
#task (rate=50ms, max=10ms)
void R_Despachador();
#task (rate=50ms, max=10ms)
void R_Llenador1();
#task (rate=50ms, max=10ms)
void R_Llenador2();
void main()
{
semaphore = 1; //Solo una tarea puede utilizar el recurso cada vez
iCantidad = 120; //Inicializamos esta variable para tener algunas botellas en
//la estera, normalmente deberiamos tener un sensor que nos reporte
//en algun momento el total de botellas en la cinta, ya que un
//robot revisor de llenado o una persona puede retirar botellas
//de la cinta
//Al comenzar todos
output_bit( PIN_B3,
output_bit( PIN_B4,
output_bit( PIN_B5,

los robots estan deshabilitados


0);
0);
0);

setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
rtos_run();
}
void R_Despachador()
{

//Note como hacemos la sincronizacion fuera de la seccion critica, mas adelante veremos
//que esto no siempre es posible hacerlo o que las cosas se complican un poco mas
//de lo que hemos visto hasta ahora.
rtos_await(iCantidad<100); //Esperemos a que se vacie un poco la cinta
output_bit( PIN_B3, 1); //A partir de aqui, si no se podia antes,

poner botellas

rtos_wait(semaphore); //Reclamamos el recurso y aqu comienza la secc crtica


if(input(PIN_B0)==1)
iCantidad++; //s es didctico y por eso lo he utilizado as.
if(iCantidad >= 100)
output_bit( PIN_B3, 0); //Le decimos al robot despachador que no ponga mas botellas
rtos_signal(semaphore); //Liberamos el semforo y aqu se acaba la sec crtica
printf("%3.0w \r",iCantidad);
rtos_yield(); // A dormir por otros 50ms para evitar poner dos veces la misma botella
}
void R_Llenador1()
{
//El robot debe esperar a que la cinta tenga suficientes botellas para sacar antes
//de comenzar a trabajar.
rtos_await(iCantidad>24); //Esperemos a que se llene un poco la cinta
output_bit( PIN_B4, 1); //A partir de aqui, si no se podia antes, sacar botellas
rtos_wait(semaphore);
if(input(PIN_B1)==1)
iCantidad -= 12;
if(iCantidad <= 24)
output_bit( PIN_B4, 0); //Le decimos al robot que no saque mas botellas
rtos_signal(semaphore);
printf("%3.0w \r",iCantidad);
rtos_yield(); // A dormir por otros 50ms para evitar poner dos veces la misma botella
}
void R_Llenador2()
{
rtos_await(iCantidad>24); //Esperemos a que se llene un poco la cinta
output_bit( PIN_B5, 1); //A partir de aqui, si no se podia antes, sacar botellas
rtos_wait(semaphore);
if(input(PIN_B2)==1)
iCantidad -= 12;
if(iCantidad <= 24)
output_bit( PIN_B5, 0); //Le decimos al robot que no saque mas botellas
rtos_signal(semaphore);
printf("%3.0w \r",iCantidad);
rtos_yield();

}
Hasta ahora solamente hemos visto ventajas del uso de los RTOS, sin embargo el uso
de estas herramientas presupone un montn de complicaciones que he tratado de no
mostrar hasta el momento, en aras de mostrar lo til que puede ser un RTOS, pero
an con esas complicaciones el uso de los RTOS sigue siendo una bendicin para
cualquier desarrollador de sistemas con uC. Simplemente tendremos que ser un poco
ms cuidadosos con la semntica de nuestros programas y pensar un poco ms en la
concepcin y modelacin de las soluciones a nuestros problemas.
En la prxima entrega vamos a ver el uso de las funciones para el paso de mensajes
entre tareas, que es otra de las ventajas que los RTOS traen al mundo de la
programacin para uC y cuando terminemos de ver todas esas cosas buenas
comenzaremos a estudiar las desgracias y cmo enfrentarlas.
[Volver al ndice]

> RTOS mail


Hasta el momento solamente hemos visto mecanismos que nos permiten simplificar el
diseo de nuestros programas, pero hoy vamos a ver una nueva potencialidad de los
RTOS que es una cuestin realmente novedosa en cuanto la visin de la programacin
para uC a la cual estamos acostumbrados.
Cuando hacemos una llamada a una funcin, es frecuente pasarle algn parmetro
para que esta pueda hacer su tarea, mientras la funcin trabaja, nuestro programa
espera pacientemente a que la funcin retorne y nos devuelva el resultado, que puede
ser un valor de retorno, un arreglo cambiado o simplemente el cambio en el estado de
algn perifrico o salidas del uC.
El prrafo anterior describe lo que hace nuestro programa cuando llamamos a una
funcin, sin embargo nunca hemos visto que una funcin le enve un dato a otra (no en
la llamada a la funcin, sino fuera de sta) para que cuando le toque ejecutarse tome
esos valores y los procese, y si hay que devolver algn resultado entonces que nos
enve un acuse de recibo. Es lgico que un mecanismo como el que acabo de describir
no se utilice en las tcnicas de programacin anterior porque la ejecucin secuencial
del cdigo presupone que no se requiera de un mecanismo como este.
Lo ms cercano al mtodo descrito en el poner datos en algn lugar para que una
funcin lo procese es el uso de las interrupciones, stas deben procesar rpidamente el
evento de interrupcin y pude que pongamos el dato en algn lugar y levantemos una
bandera para que cuando a la funcin encargada de procesar los datos le toque
ejecutarse lea la bandera, procese los datos y coloque la bandera en el estado que
notifica que ya se proces, no para notificar a otra funcin sino para notificrselo a ella
misma, no vaya a ser que cuando le toque ejecutarse nuevamente procese los mismos
resultados nuevamente o haga algo indebido.
Un ejemplo de lo anterior puede se el uso del conversor AD, en algn lugar del
programa lo mandamos a convertir; una vez hecha la conversin se produce una
interrupcin que es atendida en la correspondiente subrutina de atencin a esa
interrupcin; leemos el dato lo ponemos en una variable e incrementamos un contador.
Posteriormente le toca ejecutarse a la funcin que promedia los resultados, sta

comprueba si hay, digamos 200 muestras, si las hay hace el clculo que pone en otra
variable y deja el contador en cero. Este mecanismo es eficaz porque se ha utilizado
durante mucho tiempo, pero los RTOS brindan una solucin elegante para hacer esto
en el contexto de la ejecucin de tareas.

Estos mecanismos pueden funcionar tambin entre funciones pero tendremos el problema
de tratar con un montn de estructuras de datos, banderas y contadores, complejas
expresiones lgicas a procesar se acuerdan de eso?
Ahora imagnense hacer todo lo anterior cuando, en vez de llamadas a funciones
metidas dentro de un cdigo que se ejecuta ms o menos estructuradamente, lo que
tenemos es unas cuantas tareas de las que no tenemos un control de cuando ni como
se ejecutarn. Realmente puede ser una verdadera pesadilla hacer un programa
productivo, y es por ello que los RTOS nos ofrecen un poderoso mecanismo para hacer
eso, y como siempre, este mecanismo tambin es relativamente simple.
Para hacer lo anterior los RTOS implementan un mecanismo de mensajes. S, amigos
mos, un RTOS implementa una funcin similar a la de los correos.
El funcionamiento de ese mecanismo es simple, cuando una tarea o subrutina de
atencin a interrupciones necesita notificarle algo a otra tarea llama a una funcin que
pone el dato en la cola de la tarea en cuestin, cuando a la tarea que recibi el
mensaje le toca ejecutarse debe, en algn lugar consultar su cola de mensajes, si hay
mensajes debe leerlos y procesarlos, como pueden ver este mecanismo es bastante
parecido a lo que hacemos habitualmente.
Si yo quiero pasarles un mensaje, por ejemplo un post, hago lo siguiente:
- lo escribo, este es el equivalente a realizar una tarea
- lo mando al foro, este es el equivalente a ponerlo en la cola de mensajes del hilo
sobre RTOS
- ustedes llegan y consultan si hay mensajes nuevos en el hilo, por supuesto llegan
cuando su tarea de leer el foro est activa
- si hay un mensaje nuevo, normalmente tratarn de leerlo y poner en prctica los
nuevos conocimientos
- si se sienten impresionados, me escribirn un mensaje a mi correo privado, dndome
un acuse de recibo (no hagan esto si no es estrictamente necesario, no vaya a ser que
me vuelvan loco)
Aqu se ha puesto de manifiesto un ejemplo del sistema de mensajes ms simple
utilizado por un SO: elaborar y enviar de una parte y consultar si hay un mensaje,
procesar y enviar acuse de recibo si es necesario de la otra parte.
(Todo esto est muy bien. Pero yo quiero cdigo y ejemplos de verdad.)
Vale, no nos ofusquemos, primero entender bien el concepto, luego ponerlo en
prctica.
Lo primero que tenemos que hacer es decirle al compilador que le cree una cola de
mensajes a aquella tarea a la cual queremos pasarle mensajes, para eso tenemos el
parmetro queue, dentro de la directiva #task, con este parmetro le indicamos al
RTOS que reserve memoria y cree una cola de mensajes para la tarea, la declaracin

de una tarea con cola de mensajes sera como sigue:

El cdigo:
#task(rate = 1s, max=20ms, queue=5)
void Tarea1(void);
En la declaracin de la tarea el parmetro queue = 5, le dice al compilador que cree
una cola de 5 bytes para la Tarea1.
Para el envo y recepcin de mensajes tenemos las siguientes funciones:
RTOS_MSG_SEND( )
RTOS_MSG_POLL( )
RTOS_MSG_READ( )
RTOS_MSG_SEND(task, byte); permite enviar un byte de datos a la cola de mensajes
de una tarea. Esta es la nica funcin del RTOS de CCS que puede llamarse desde
fuera de una tarea, lo que permite que desde una subrutina de atencin a interrupcin
se le enven mensajes a una tarea. El parmetro task es para el nombre de la tarea y
byte es un dato de 8 bits (un char o un int8), as que si queremos enviar un float o una
estructura tendremos que descomponer antes ese dato en bytes y luego componerlos
cuando la cola de mensajes sea leda.
int RTOS_MSG_POLL(); es la funcin que permite a una tarea conocer si tiene
mensajes en su cola de mensajes, no se puede llamar desde otra tarea para conocer
cuantos mensajes tiene la tarea fulana. Devuelve en un entero la cantidad de bytes
ocupados dentro de la cola de mensajes.
int8 RTOS_MSG_READ(); permite leer un byte de la cola de mensajes. Cuando se
ejecuta esta funcin se lee el byte y se saca de la cola, por lo que si el dato se pierde
no se podr recuperar, si se llama a la funcin y no hay mensajes en la cola se pueden
obtener datos falsos.
En el ejemplo que hemos estado viendo sobre la embotelladora, vamos a incluir un
servicio especial para balancear la cantidad de botellas que hay dentro de la cinta
transportadora, para ello pondremos una tarea adicional que recibir de las otras
tareas el estado de la cantidad de botellas dentro de la cinta. Si la cinta se est
vaciando demasiado rpido, esta tarea se encargar de inhabilitar los robots llenadores
de cajas, si se est llenando muy rpido pues entonces se deshabilita al robot que
despacha botellas hacia la cinta.
Para lograr esto cada vez que un robot ejecuta la tarea de llenado de cajas o despacho
de botellas le notifica a la tarea reguladora la cantidad de botellas que hay en la cinta,
con este mecanismo evitamos que la tarea supervisora tenga que leer el recurso
compartido iCantidad, y que tenga que sincronizarse con los robots. La cola de
mensajes tendr dos bytes (aunque solo se necesita uno, despus explico por que
hacen falta dos) donde se reflejar la ltima escritura realizada por cualquiera de los
tres robots. Adems, delegaremos en esta tarea la transmisin de la cantidad de
botellas que hay en la cinta. La cantidad media de botellas a tener en la cinta es 50.
El cdigo:
#include "D:\Documentos\Projects\RTOS\RTOS.h"
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=9)

#use RTOS(timer=0, minor_cycle=10ms)


int8 semaphore; //Este es nuestro semforo
int8 iCantidad; //Esta es la cantidad de botellas en la estera
//constituye nuestro recurso compartido
#task (rate=50ms, max=10ms)
void R_Despachador();
#task (rate=50ms, max=10ms)
void R_Llenador1();
#task (rate=50ms, max=10ms)
void R_Llenador2();
#task (rate=1s, max=10ms, queue=2) //la cola tiene 2 byte aunque solamente necesitamos 1
void Supervisor();
void main()
{
semaphore = 1; //Solo una tarea puede utilizar el recurso cada vez
iCantidad = 120; //Inicializamos esta variable para tener algunas botellas en
//la estera, normalmente deberiamos tener un sensor que nos reporte
//en algun momento el total de botellas en la cinta, ya que un
//robot revisor de llenado o una persona puede retirar botellas
//de la cinta
//Al comenzar todos
output_bit( PIN_B3,
output_bit( PIN_B4,
output_bit( PIN_B5,

los robots estan deshabilitados


0);
0);
0);

setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
rtos_run();
}
void R_Despachador()
{
//Note como hacemos la sincronizacion fuera de la seccion critica, mas adelante veremos
//que esto no siempre es posible hacerlo o que las cosas se complican un poco mas
//de lo que hemos visto hasta ahora.
rtos_await(iCantidad<100); //Esperemos a que se vacie un poco la cinta
output_bit( PIN_B3, 1); //A partir de aqui, si no se podia antes,

poner botellas

rtos_wait(semaphore); //Reclamamos el recurso y aqu comienza la secc crtica


if(input(PIN_B0)==1)
iCantidad++; //s es didctico y por eso lo he utilizado as.
if(iCantidad >= 100)
output_bit( PIN_B3, 0); //Le decimos al robot despachador que no ponga mas botellas
rtos_msg_send(Supervisor, iCantidad); //Enviamos un mensaje con la cant de botellas
rtos_signal(semaphore); //Liberamos el semforo y aqu se acaba la sec crtica
rtos_yield(); // A dormir por otros 50ms para evitar poner dos veces la misma botella
}

void R_Llenador1()
{
//El robot debe esperar a que la cinta tenga suficientes botellas para sacar antes
//de comenzar a trabajar.
rtos_await(iCantidad>24); //Esperemos a que se llene un poco la cinta
output_bit( PIN_B4, 1); //A partir de aqui, si no se podia antes, sacar botellas
rtos_wait(semaphore);
if(input(PIN_B1)==1)
iCantidad -= 12;
if(iCantidad <= 24)
output_bit( PIN_B4, 0); //Le decimos al robot que no saque mas botellas
rtos_msg_send(Supervisor, iCantidad);

//Enviamos un mensaje con la cant de botellas

rtos_signal(semaphore);
rtos_yield(); // A dormir por otros 50ms para evitar poner dos veces la misma botella
}
void R_Llenador2()
{
rtos_await(iCantidad>24); //Esperemos a que se llene un poco la cinta
output_bit( PIN_B5, 1); //A partir de aqui, si no se podia antes, sacar botellas
rtos_wait(semaphore);
if(input(PIN_B2)==1)
iCantidad -= 12;
if(iCantidad <= 24)
output_bit( PIN_B5, 0); //Le decimos al robot que no saque mas botellas
rtos_msg_send(Supervisor, iCantidad); //Enviamos un mensaje con la cant de botellas
rtos_signal(semaphore);
rtos_yield();
}
void Supervisor()
{
int8 iBotellas;
rtos_await(rtos_msg_poll()>0);

//Esperamos a que haya algun mensaje en la cola

iBotellas = rtos_msg_read(); //Leemos el mensaje


//Lo que hacemos ahora es comprobar la cantidad de botellas que hay en la estera
//y en funcion de eso habilitamos y deshabilitamos las tareas y los robots que hacen
falta
//para controlar la cantidad de botellas en la estera
if(iBotellas > 50)
{
output_bit( PIN_B3, 0); //No despachar mas botellas

rtos_disable(R_Despachador);
rtos_enable(R_Llenador1);
rtos_enable(R_Llenador2);
}
else
{
rtos_enable(R_Despachador);

//No llenar mas cajas

output_bit( PIN_B4, 0);


rtos_disable(R_Llenador1);
output_bit( PIN_B5, 0);
rtos_disable(R_Llenador2);
}
printf("%3.0w \r",iBotellas);

//Transmitir la cantidad de botellas

}
Este programa se puede simular con el mismo fichero de Proteus que publiqu antes,
noten como la cantidad de botellas en la cinta transportadora se mantiene sobre las 50
botellas. En el caso de la cola de mensajes deben especificar n+1 bytes de los que
necesiten, la razn no la conozco pero con 1 byte no funciona, debe ser algn
problema de la implementacin de CCS o alguna limitacin de los PIC que obliga a ello.
Bueno espero que les sirva.
PD: Lo de esta embotelladora es un invento, en ningn momento esto se ha probado
en una planta de ese tipo.
El tiempo que utilic para este ejemplo fue de 3:30 horas, incluyendo la redaccin y
programacin.
[Volver al ndice]

Interrupciones! A M!
La oracin anterior me hace parecer sper hroe. Aunque yo no lo sea, pero con un
RTOS y la tcnica que veremos hoy, puedo considerarme uno de ellos, al menos en la
programacin de microcontroladores, y despus de hoy, todos podemos aspirar a ser
un RTOS PIC SPER-HROE.
En la entrega anterior estudiamos el paso de mensajes, pero solamente vimos el paso
de mensajes entre tareas, esta posibilidad de los RTOS es poderosa y adems es el
mejor mtodo para pasar informacin de una tarea a otra, por su sencillez. El paso de
mensajes es una necesidad de los SO, porque como expliqu, las tareas no son como
las funciones, a las cuales un segmento de cdigo llama y se queda esperando hasta
que la funcin retorna. Entonces como no sabemos en que momento una tarea entrar
en su contexto, hay que crear un mecanismo eficiente para que trabaje con los datos
que debe servir otra parte del cdigo.
Adems de lo anterior, durante todo el cursillo, no hemos visto ni utilizado ninguna
interrupcin y eso, desde mi punto de vista, no es nada bueno. Los procesos de

interrupcin nos permiten atender con eficiencia procesos asincrnicos como la


conversin analgica, la escritura en memorias EEPROM, las interrupciones externas, la
recepcin de datos por la USAR, el PSP o el MSSP y tambin procesos sincrnicos como
los que producen los temporizadores.
Pero el uso de un RTOS, nos plantea un dilema con el uso de las interrupciones, ya que
en principio cuando utilizamos un RTOS estamos imponiendo que las tareas se van a
ejecutar ms o menos cada cierto tiempo o que estarn bloqueadas en espera de algo.
Por lo tanto, si deseamos que una tarea atienda un proceso asincrnico, sta debe
hacerlo por encuesta, es decir cuando le toque ejecutarse debe comprobar si hay
informacin que procesar. Por otro lado, las interrupciones cuando ocurren, deben ser
atendidas en el instante y no cuando al RTOS considere que deben ser atendidas.
Ahora tenemos por un lado una herramienta que nos obliga a utilizar los mecanismos
de encuesta, el RTOS, pero que nos ayuda a crear cdigo robusto, eficiente y con
velocidad, ventajas nada despreciables. Por otro tenemos un mecanismo para atender
procesos que no pueden esperar mucho tiempo en ser atendidos o se corre el riesgo de
perder la informacin, y perder datos es inaceptable para un sistema embebido.
Entonces: cmo hacer para aprovechar de las ventajas de ambos?
Para solucionar este problema los RTOS deben permitir que desde una ISR (subrutina
de atencin a interrupcin) podamos pasarle mensajes a cualquier tarea que lo
requiera. Vamos a ver esta ventaja con un ejemplito simple.
Supongamos que tenemos una aplicacin que tiene varias tareas, entre ellas hay una
dedicada a atender la recepcin de datos por el puerto serie, sta tarea se ejecuta con
una frecuencia que permite procesar los datos que llegan desde el puerto serie. Un
mtodo para hacerlo sera, que cada vez que a la tarea le toque ejecutarse, sta
compruebe si ha llegado un dato al puerto serie para tomarlo y procesarlo. Eso est
bien, pero que pasa si mientras la tarea est esperando su turno de ejecutarse llega
ms de un dato al puerto serie, por supuesto que se perdern datos y esto si que no
podemos permitirlo.
La solucin al problema anterior es separar la atencin de la llegada de datos al puerto
serie del procesamiento de los datos recibidos, para ello dejamos en manos de una ISR
la lectura del registro de datos y el control de los registros de estado del puerto serie y
que la tarea se encargue, cada cierto tiempo, de procesar la informacin recibida.
El mtodo anterior se puede implementar si el RTOS permite el paso de mensajes
desde una ISR hacia una tarea del RTOS, invocando una funcin adecuada. De esta
forma cuando se produzca la interrupcin y nos vayamos hasta la ISR, lo que tenemos
que hacer es leer el dato y mandarle un mensaje a la tarea, si llega otro dato lo
leemos y lo mandamos y as sucesivamente, si la tarea tiene una cola de mensajes
suficientemente larga, no debemos perder datos en la recepcin por el puerto serie,
an cuando la tarea se ejecute con una frecuencia menor que la de recepcin de datos
en el puerto serie.
En el ejemplo de hoy vamos a hacer con RTOS algo parecido a lo que hace la funcin
gets(), con la diferencia de que en vez de quedarnos como tontos esperando a que
llegue el carcter de fin de lnea o retorno de lnea vamos a ceder el procesador cada
vez que comprobemos que no ha llegado el carcter de terminacin adecuado.
Para la implementacin utilizaremos dos PIC16F877, en uno de ellos pondremos un

programa que enva una cadena por el puerto serie hasta el otro PIC con una
frecuencia de 3 segundos. El PIC que recibe los datos, implementa esta funcionalidad
mediante la interrupcin de la USART, los cuales pone en la cola de una tarea, la cual
va reconstruyendo la cadena, hasta que esta est completa y entonces tambin la
enva por su USART.
Este es el cdigo del PIC que enva la cadena:
#include "D:\Documentos\Projects\RTOS\RTOS.h"
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=9)
#use RTOS(timer=0, minor_cycle=10ms)
int8 iBuffer; //Indice en el buffer para ir llenandolo
#task (rate=3s, max=10ms) //Creamos una cola con 10 bytes utiles
void Serial();
void main()
{
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
rtos_run();
}
void Serial()
{
printf("Prueba\n");
}

y este el del PIC que recibe y retransmite la cadena:


#include "D:\Documentos\Projects\RTOS\RTOS.h"
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=9)
#use RTOS(timer=0, minor_cycle=10us)
char cBuffer[17] ; //Aqui guardamos el texto a enviar por el puerto serie
int8 iBuffer; //Indice en el buffer para ir llenandolo
#task (rate=100us, max=10us, queue = 3) //Creamos una cola con 2 bytes utiles
void Serial();
void main()
{
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
enable_interrupts(GLOBAL);
enable_interrupts(INT_RDA);
rtos_run();
}
void Serial()
{
char cDato;
rtos_await(rtos_msg_poll()); //Esperamos hasta que haya algun dato en cola
while(rtos_msg_poll()) //Procesamos la cola completa

{
cDato = rtos_msg_read();
cBuffer[iBuffer] = cDato;
iBuffer++;
}
if(iBuffer == 16 || cDato == '\n') //Si esta toda la cadena la enviamos
{
printf("%s\r", cBuffer);
iBuffer = 0;
}
}
#INT_RDA
void fINT_RDA(void)
{
rtos_msg_send(Serial, getc()); //Tomamos el dato del buffer y lo ponemos en la cola
}
Aqu est el fichero con los programas y la simulacin en Proteus: RTOS_ISR.ZIP (35K,
formato zip)
Como vern en la implementacin de estos programas he puesto al PIC que
retransmite los datos a ejecutar su tarea que procesa los datos recibidos por el puerto
serie con una frecuencia mucho mayor que la del PIC que le enva los datos, incluso es
mucho ms rpida que la velocidad de transmisin recepcin de los mensajes, esto me
permite tener una cola muy pequea y que los mensajes no se pierdan.
Yo les aconsejo que jueguen con la frecuencia de ejecucin de la tarea, (parmetro
rate en la declaracin #task) en el PIC que retransmite, y el tamao de la cola, vern
como la cadena a veces se corta, en ocasiones el PIC no retransmite nada. Pero esto
les dar una idea de cmo funciona el mecanismo.
Si por ejemplo aumentan la frecuencia de ejecucin pueden poner una cola ms
pequea, es el cdigo del ejemplo. Si tienen una frecuencia menor, entonces tendrn
que poner una cola ms grande para que el mensaje quepa completo.
Otra solucin a este problema es que la ISR escriba directamente en el Buffer y
solamente le mande un mensaje a la tarea cuando se haya recibido el mensaje
completo para que esta lo retransmita. Con esto ahorramos memoria RAM, ya que
podemos poner una cola muy pequea, adems podemos transferirle a la tarea que
atienda los mensajes de error, el procesamiento de comandos y cosas por el estilo.
Todo depende de la aplicacin y de la imaginacin del programador.
Me tom 1:30 horas escribir el programa y ponerlo a punto, otra hora para escribir el
texto y varios das para pensar como enfocarles el problema. Ahora es tarea de
ustedes poner todo esto en prctica.
Les propongo que hagan un programa para enviar datos por la USART, similar a
printf(), pero ms eficiente. Pueden por ejemplo utilizar sprintf(), para poner la cadena
en RAM y despus que la tarea configure el servicio de interrupciones, mande el primer
byte y la ISR enve el resto, cuando la ISR termine debe notificar a la tarea que ya est
en condiciones de enviar ms datos, de modo que la tarea le puede crear otra cadena
y volver a mandar a transmitir. Notarn que hay que tener unas cuantas cosillas en

cuenta, pero es un buen problema para practicar.


Un saludo Reinier.
[Volver al ndice]

> Volviendo sobre nuestros pasos:


Hasta el momento hemos visto que los RTOS pueden ser muy tiles al enfrentar la
implementacin de aplicaciones complejas, ellos nos ofrecen herramientas poderosas y
simples que facilitan el desarrollo rpido de aplicaciones, las desventajas
fundamentales que hemos estado viendo son aceptables cuando las comparamos con
los beneficios que obtenemos por utilizar un RTOS.
Hasta hace algn tiempo, el diseo de sistemas con microcontroladores se enfrentaba
con horas y horas delante de una PC o con una hoja de papel, escribiendo cdigo en
ensamblador y pasando mucho trabajo para que cualquier cosa que disesemos
funcionara, eso solamente en teora, ni que decir de llevar esos diseos a la prctica, y
tener que lidiar entonces con las PCB, circuitos haciendo cosas extraas y dems.
Con la llegada de los compiladores para lenguajes como C, PASCAL, BASIC y
simuladores avanzados como el PROTEUS, los desarrolladores de aplicaciones han
tenido un importante respiro para llevar adelante sus diseos. Pero el mercado, y los
consumidores se han vuelto ms exigentes y la parada ha tenido que subir un poco, la
solucin: utilizar sistemas operativos en los dispositivos embebidos.
Como toda maravilla tecnolgica, el uso de un SO requiere muchas veces perder
ciertas ventajas respecto a los mtodos anteriores. Cuando programbamos en
ensamblador obtenamos el mximo en desempeo y aprovechamiento del
microcontrolador pero el desarrollo y puesta a punto era muy lento y las aplicaciones
podan tener errores muy difciles de detectar.
Los compiladores mejoraron el problema de los errores y redujeron considerablemente
el tiempo de desarrollo, pero los programas gastan ms memoria de programa,
memoria de datos y son ms lentos en ejecucin.
Los SO aumentan las desventajas de los compiladores pero mejoran el desarrollo de
aplicaciones en muchos otros aspectos.
La solucin al dilema de eficiencia vs. eficacia nos la ofrecen los mismos fabricantes de
microcontroladores, al disear dispositivos cada vez ms rpidos y con ms memoria.
Ahora podemos simplemente movernos entre las diferentes gamas y familias de
dispositivos buscando el que se adapta mejor a nuestras necesidades y utilizar
mtodos de diseo tan avanzados como los RTOS. Los precios no son el mayor
problema como antao, incluso algunos uC ya obsoletos salen ms caros que sus
sustitutos.
Toda la explicacin anterior est destinada a refrescar el por qu utilizar un RTOS
respecto de utilizar los medios que hemos venido utilizando hasta el momento y
porque a partir de ahora comenzaremos a ver los peligros de implementar aplicaciones
con el uso de este tipo de herramientas.
La mayor pesadilla para cualquier programador es que su aplicacin se bloquee o

cuelgue y el sistema deje de trabajar como debe, este tipo de problemas es muy
frecuente en sistemas operativos orientados a usuarios como Windows y en menor
medida GNU/LINUX, la razn para ello est en la diversidad de aplicaciones que puede
utilizar un usuario, los errores de estos programas, los propios del SO, la capacidad del
usuario para hacer que el SO colapse (conozco varios usuarios expertos en esta
materia), etc.
Al utilizar un RTOS para programar aplicaciones nos estamos enfrentando al problema
de crear aplicaciones que tienen alta probabilidad de bloquear al sistema, ello est
dado porque las cosas que debe hacer el sistema estn divididas en procesos o tareas
que se ejecutan de forma ms o menos independiente del resto, compartiendo
recursos del sistema y compitiendo por ellos. A todo lo anterior hay que sumarle que
en el momento de la ejecucin, el SO no tiene idea de que orden lleva la ejecucin de
los procesos o cuanto tiempo le tomar a un proceso terminar su ejecucin, es por eso
que no se pueden programar aplicaciones para SO en base a suposiciones en el orden
de ejecucin de las tareas o los tiempos requeridos para su completamiento.
Todo lo anterior puede asustarnos mucho porque implica que programar utilizando
RTOS es potencialmente peligroso, y s, ES PELIGROSO! Pero ms que peligroso es
complicado y puede ser muy tedioso, ya que se complica la semntica y la depuracin
de las aplicaciones, pero eso no debe ser motivo de desaliento, ya que existen tcnicas
para reducir esas complicaciones y los problemas estn debidamente identificados. Y
eso es lo que vamos a comenzar a tratar en las prximas entregas.
Existen muchos problemas con los que los diseadores deben lidiar al programar
utilizando un SO, pero en nuestro caso, por las caractersticas de nuestros dispositivos,
estamos salvados de un buen nmero de ellas. Sin embargo Nmesis ha querido de
todas formas poner un lmite a nuestra dicha, y nos ha obsequiado dos clases de
problemas que pueden hacernos perder la razn si decidimos utilizar un RTOS:
* Condiciones de competencia
* Bloqueo mutuo
En las prximas entregas iremos viendo poco a poco cada una de estas clases de
problemas, como detectar los problemas, ejemplos tipos de aplicaciones en que se
presentan y como enfrentar estas dificultades.
El arma fundamental con que contamos est en utilizar correctamente los mecanismos
de coordinacin y sincronizacin, ya que el mal uso de ellos es una da las causas que
pueden provocar una condicin de competencia o un bloque mutuo, otras veces el
hecho est en un diseo chapucero, mal pensado, errores semnticos en el cdigo o
simplemente que no haya solucin al problema (aunque esto ltimo es muy poco
frecuente o muy difcil de detectar).
Ahora, como veremos prximamente, aprender a programar con un RTOS es mucho
ms complicado de lo que hemos visto hasta el momento, pero yo no quise meterles
miedo y poner los problemas por delante de las ventajas de los RTOS, sino mostrarles
un poco de lo mucho que se puede hacer para luego meternos con los problemas a los
que debemos enfrentarnos.
Como han podido apreciar, hoy no tengo ninguna aplicacin que mostrarles, pero no se
desalienten porque prximamente vamos a toparnos con cada programita que ya

ustedes tendrn de sobra para dolores de cabeza, pero al final cada uno de ustedes
estar en condiciones de enfrentarse a la solucin de aplicaciones difciles de
implementar en muy poco tiempo, podrn tambin estudiar y profundizar en la teora
de los Sistemas Operativos sin muchas dificultades y si explotan bien lo aprendido
podrn llegar a ser profesionales muy competitivos y capaces.

Nocturno pregunta: "No acabo de entender cul es el problema. Si el RTOS pone una
bandera cuando utiliza un recurso del micro y antes de utilizarlo mira si la bandera la
ha puesto otro proceso no debera haber problemas."
Ya que el amigo Nocturno lo pide, voy a a darles un adelanto:
Los SO cooperativo tienen la ventaja de mejorar un poco los problemas de los que les
he estado hablando, pero an as estos se pueden presentar.
Imaginen que tenemos dos tareas, A y B, que deben esperar por dos semforos pra
poder hacer su trabajo, es decir, por alguna razn estas tareas necesitan acceder a
recursos compartidos a las que tienen derecho otras tareas, digamos que C tiene
acceso al semforo 1 y D al semforo 2. Por razones de diseo, estos recursos
compartidos no pueden accederse con un solo semforo pero A y B necesitan acceso
exclusivo a los dos recursos para poder trabajar. mientras que C y D solamente
necesitan de uno de los recursos.
Ahora A toma el control del semforo 1 y como el otro est siendo utilizado por D, se
queda a esperar pacientemente entregando el procesador. Luego D termina de
ejecutarse y libera el semforo pero en ese momento B comienza a ejecutarse y toma
el control del semforo 2 por lo que debe quedarse a esperar por el semforo 1, que
est en poder de la tarea A y como este espera por el semforo 2, no podr continuar
ejecutndose, pero tampoco B que espera por el semforo 1. Ahora C y D tampoco
pueden ejecutarse porque sus semforos estn en poder de otras tareas (A y B que
estn en una espera circular que nunca termina), as que se ha producido una
condicin de competencia y el sistema se ha colgado.
Como pueden ver es bastante enredado explicar una situacin de condicin de
competencia y es por eso que es difcil darse cuenta cuando existe una de ellas. En el
ejemplo anterior tenemos un caso de un diseo con una semntica mal diseada, que
se puede resolver fcilmente como veremos, pero si el SO fuese de tiempo compartido
los problemas seran ms difciles de evitar.
Ms adelante iremos viendo estos problemas con ms detalle.
Un saludo Reinier
[Volver al ndice]

> Las condiciones de competencia:


Como introduje en los posts anteriores, las condiciones de competencia son uno de los
problemas potenciales que se presentan en la programacin con Sistemas Operativos,
pero: Qu es una condicin de competencia?

Bsicamente es una bronca entre procesos que termina con el cuelgue de nuestro
sistema, pero esa no es una definicin apropiada para este problema, una mas
acertada sera esta: una condicin de competencia es un fenmeno que se produce
cuando uno o varios procesos compiten por uno o varios recursos produciendo el
bloqueo en la ejecucin de esos procesos, lo que a la postre termina con el cuelgue del
sistema.
Entonces una condicin de competencia es una de las pesadillas que un programador
de aplicaciones que utiliza algn Sistema Operativo debe evitar si desea dormir
tranquilamente. En mi post anterior puse un ejemplo en el cual se produce una
condicin de competencia, si se analiza con ms detenimiento podemos darnos cuenta
que es muy difcil definir bajo que condiciones se producir una condicin de
competencia; sin embargo, como este es un tema investigado desde los aos 60, un
grupo de gente ya se ha ocupado de identificar bajo que condiciones un programa ser
robusto ante condiciones de competencia.
Para evitar una condicin de competencia debemos establecer un conjunto de reglas
que nos aseguren que no se producir, adicionalmente, el Sistema Operativo debe
ofrecer al programador un conjunto de herramientas de programacin que le permitan
poner en prctica estas reglas.
De hecho, a lo largo del curso en los ejemplos que he puesto, hemos estado evitando
las condiciones de competencia, slo que no se los dije para no complicar las cosas
ms de lo que ya eran en aquel entonces, pero es el momento de tocar este tema y
aqu vamos.
La regla de oro para evitar las condiciones de competencia es garantizar el acceso
seguro a recursos compartidos, es decir, debemos hacer coordinacin y sincronizacin
de procesos.
Para lograr implementar esta regla es que se inventaron las secciones crticas, pero el
utilizar las herramientas de implementacin de secciones crticas no asegura evitar una
condicin de competencia, ese es el caso del ejemplo de mi mensaje anterior.
Bien, si an utilizando secciones crticas no se asegura evitar que se produzca una
condicin de competencia, que podemos hacer para resolver el problema? Lo que
podemos hacer es poner restricciones en la semntica de nuestro cdigo que aseguren
que el cdigo es seguro, valga la redundancia.
El prrafo anterior nos pone otra vez en aprietos porque debemos preguntarnos
entonces cuales son esas restricciones semnticas? La respuesta a esa pregunta est
dada en las siguientes cuatro reglas que debemos cumplir:

Dos o ms procesos no pueden estar simultneamente dentro de sus regiones


crticas
No debe suponerse nada acerca de la velocidad o el orden de ejecucin de los
procesos
Ningn proceso que se ejecute fuera de su regin crtica puede bloquear a otros
procesos
Ningn proceso deber tener que esperar indefinidamente para entrar a su
regin crtica

Como veremos en el futuro, hacer que nuestros programas cumplan con estas
restricciones puede ser realmente doloroso, (al menos para nuestra cabeza), pero
tambin veremos que ya algunos se rompieron la cabeza por nosotros y nos ofrecen
soluciones tipo para la mayora de los problemas a los que debemos enfrentarnos,
estas soluciones se presentan con ejemplos bastante didcticos que perecen tonteras
pero que podemos trasladar a problemas reales que son muy semejantes en su
dinmica.
Ahora analicemos detalladamente cada una de las reglas semnticas que debe cumplir
un programa libre de condiciones de competencia:
Dos o ms procesos no pueden estar simultneamente dentro de sus regiones
crticas
Cuando introduje las secciones crticas expliqu que su misin fundamental era evitar
que ms de un proceso accediera a un recurso compartido, esto implica que para ello
debemos contar con algn mecanismo de proteccin y este mecanismo result ser el
uso de semforos, pero los semforos por si solos no garantizan la ejecucin segura,
debemos pensar donde ponerlos y cuantos necesitamos para evitar que ms de un
proceso se meta en el cdigo que manipula al recurso compartido.
En ocasiones se permite que ms de un proceso acceda al recurso compartido para
realizar lecturas pero cuando se hagan escrituras debemos impedir que ms de un
proceso est dentro de la seccin crtica, esta es una variacin a la regla tal como la
hemos definido, pero esta situacin se da en muy contadas ocasiones as que no
debemos preocuparnos mucho por esta variacin.
No debe suponerse nada acerca de la velocidad o el orden de ejecucin de los
procesos
Este es un tema que podemos subestimar porque tradicionalmente programamos
pensando que tenemos para nosotros todo el equipo de cmputo, pero cuando
utilizamos Sistemas Operativos las condiciones cambian mucho porque cada proceso
acta como si todo el equipo de cmputo fuese suyo en el momento en que est
ejecutndose, por lo que debemos proteger los recursos compartidos adecuadamente
ante los cambios de contexto de los procesos.
Para ello existen, por supuesto, las secciones crticas; pero esta nueva regla le indica al
programador que no puede soportar la semntica de su programa en suposiciones de
carcter temporal o de orden de ejecucin de los procesos y eso qued claro en uno de
los primeros ejemplos que puse en este cursillo.
Ningn proceso que se ejecute fuera de su regin crtica puede bloquear a
otros procesos
Esta regla lo que define es que el bloqueo a otros procesos debe realizarse justo antes
de entrar a la seccin crtica, para evitar que otro proceso sea detenido cuando en
realidad puede ejecutar cdigo de forma segura, igualmente los procesos que hayan
sido bloqueados cuando se entr en la seccin crtica deben ser desbloquedaos al salir
de esta.
Adems al poner en prctica esta regla reducimos al mximo el tamao del cdigo

dentro de la seccin crtica y con ello maximizamos el uso de la CPU y minimizamos los
tiempos de bloqueo, as que aunque parece simple de poner en prctica, veremos que
no es tan simple lograr estos objetivos.
Ningn proceso deber tener que esperar indefinidamente para entrar a su
regin crtica
Ahora se trata de evitar que un proceso muera de inanicin, es decir, que estando listo
para ejecutarse y requiriendo que se ejecute, otro proceso mucho ms rpido o
prioritario bloquee a uno ms lento, menos prioritario o ambas cosas a la vez,
matndolo de hambre. Este problema puede ser muy solapado y por ello muy
peligroso.
Normalmente los sistemas de planificacin de procesos de los Sistemas Operativos
implementan mecanismos que tratan de evitar el fenmeno de inanicin, pero estos
mecanismos no son infalibles y los programadores debemos estar pendientes de lo que
hacemos para evitarlo.
Hasta aqu el post de hoy porque ya tengo dolor de cabeza y creo que es suficiente
materia para provocarle el mismo problema a alguno de ustedes. En la prxima
entrega comenzamos a ver problemas y programas para evitar las condiciones de
competencia as que preparen los compiladores y el coco, tengan agua o hielo cerca
para refrescarlo y no se asusten que esto es difcil pero no imposible.
[Volver al ndice]
> Datos de Contacto:
Los datos de contacto de Reinier son los siguientes:
e-mail: reiniertl@gmail.com
Ciudad de La Habana, Cuba
WEB provisional: http://reinier-torres-labrada.neurona.com
[Volver al ndice]

> Bibliografa:
- Sistemas Operativos Diseo e Implementacin. Andrew S. Tanenbaum.
[Volver al ndice]

S-ar putea să vă placă și