Schedulers para micro sin SO para beginners

160 views
Skip to first unread message

Geni Suarez

unread,
Jan 10, 2017, 7:26:11 AM1/10/17
to Embebidos32
Buen año a todos, 
estoy indagando sobre la forma de realizar un scheduler a partir de un/os timers. Dicen que todo profesional de los sistemas embebidos alguna vez se montó alguno. Lo cierto es que montar montar yo todavía no me monté ninguno. He usado y medio modificado alguno; pero tengo muchas lagunas o ni me acuerdo. He planificado tareas teniendo ya el scheduler del sistema disponible. Pero sin entrar en detalle al planificador. Viendo las fuentes que consulto tengo todo "borroso" y desordenado en mi mente. No sabría ni por dónde empezar.
Como todo supongo que existen muchas formas de hacerlo dependiendo de la plataforma, tipo de tareas, nº de tareas, etc.. 
Digamos que para empezar estaría pensando en consejos para un micro con no muchos recursos, planificador sencillo, no preventivo, con no muchas tareas y cada una se inicie en diferente temporización. Me imagino usando un timer para cada tarea y que ande contando; pero cuando son ni muchas ni pocas quizás no sea factible usar un por cada tarea.
Si tenéis sugerencias u opinión sobre al menos una posible secuencia de pasos a llevar a la estructura de un algoritmo (trabajo en C) o algún enlace con una buena y ordenada explicación/ejemplos. 

Que tengáis un buen día.

Christian N

unread,
Jan 10, 2017, 8:11:51 AM1/10/17
to Embebidos32
Hola Geni

Para realizar un scheduler no solo es importante el algoritmo de organizacion de la secuencia de las tareas sino el metodo utilizado para realizar la conmutacion.
Cada tarea tiene su contexto , el cual puede dividirse entre el espacio de contexto y el contexto en si mismo.
Para realizar la conmutacion, independientemente si utilizas un lista enlazada con las tareas a ejecutar, un round robin o lo que mas te guste, tenes que planificar como vas a gestionar la proteccion de los datos (registros y zonas de memoria) de cada tarea, comprender los recursos del procesador a utilizar y sobre todo la arquitectura.
Una web que es de utilidad es la http://wiki.osdev.org/Main_Page. Para una introduccion sobre los recursos puestos en juego en la arquitectura Intel http://wiki.electron.frba.utn.edu.ar/doku.php?id=td3:start (seria mala persona si te mandara a leer el volumen 3 de Software Development Manual de Intel)
Respecto al lenguaje de programacion, si bien podes realizarlo 85% en C, la conmutacion final inevitablemente te obliga a ir a ASM, ademas de que por no tener un OS practicamente tenes que realizarlo en baremetal, asi que algo de ASM vas a tener que meter.

Una cuestion tal vez no menor del mail que enviaste es que no tenes un timer por cada tarea, al menos no uno fisico, sino que tenes un unico timer asociado a una interrupcion y unos de los metodos es que esta cuente los ticks y estando el scheduler dentro del temporizador selecciona la proxima tarea a conmutar en base a un contador asociado a cada una que representa el time slot

Obviamente no hay mail que pueda responder en forma detallada la pregunta, pero repregunta y se armando algo mas enfocado

Geni Suarez

unread,
Jan 10, 2017, 8:40:20 AM1/10/17
to Embebidos32
Grcias Christian, pero vamos a intentarlo:

Realmente quisiera planificar algo muy básico para empezar por lo sencillo, más adelante ya incrementaría el nivel de complejidad.
Imaginemos 4 tareas o 5 a lo sumo; funciones que se ejecutan cuando son llamadas y está previsto que sean llamadas cuando ha pasado una cierta cantidad de tiempo (diferente en cada una) y que no son preventivas (no deben ser interrumpidas). Si me apuras a concretar un dato más, algunas pueden lanzar llamadas al driver, como sea leer o escribir en algún registro GPIO. 
Me gustaría saber cómo se escribe un planificador. Dónde y cómo se define, etc.. y bueno una estructura. Supongo que puedo tener un timer corriendo que al llegar a determinados valores active un flag. Luego fuera del timer ya comparo el flag (p ej: por polling) y si cambió entonces lanzo la tarea correspondiente. Así hasta que las n tareas hayan sido lanzadas de forma cíclica. Si alguna no puede lanzarse porque está en ejecución la anterior no pasa nada, ya saldrá cuando esté libre y le toque turno. 
Esa sería mi idea conceptual de lo que trataría de llevar a código.

Por cierto,  muy interesante ese link, lleva de todo.

Fernando Mondello

unread,
Jan 10, 2017, 8:50:07 AM1/10/17
to embeb...@googlegroups.com
Hay varios libros que cubren el tipo de algoritmo que estás buscando. Los que recuerdo son:

"Real-Time Embedded Systems" - Xiaocong Fan
"Embedded Systems Building Blocks" - Jean Labrosse

Podés buscar en la web bajo los términos: "Timing wheel C", "Timer wheel C" o "Software timers C". Hay muchas implementaciones dando vueltas.
Hay uno bastante interesante, que a diferencia del resto, está basado en eventos:



Saludos,
Fernando Mondello

--
-- Recibiste este mensaje porque estás suscripto al Grupo Google Embebidos32. Para postear en este grupo, escribe un email a embeb...@googlegroups.com. Para des-suscribirte, envía un email a embebidos32+unsubscribe@googlegroups.com. Para más opciones, visita el sitio del grupo en https://groups.google.com/d/forum/embebidos32?hl=es
---
Has recibido este mensaje porque estás suscrito al grupo "Embebidos32" de Grupos de Google.
Para cancelar la suscripción a este grupo y dejar de recibir sus mensajes, envía un correo electrónico a embebidos32+unsubscribe@googlegroups.com.
Para acceder a más opciones, visita https://groups.google.com/d/optout.



--
Saludos,
Fernando Mondello

Franco Bucafusco

unread,
Jan 10, 2017, 8:51:20 AM1/10/17
to embeb...@googlegroups.com
Hola Geni,

Creo que deberias usar algun planificador bien sencillo.

Podes leer el libro gratuito http://www.safetty.net/publications/pttes
en donde te podes bajar tambien codigo fuente.

sds!

F

Geni Suarez

unread,
Jan 10, 2017, 8:53:26 AM1/10/17
to Embebidos32
Muy agradecida Fernando :)


El martes, 10 de enero de 2017, 14:50:07 (UTC+1), Fernando Mondello escribió:
Hay varios libros que cubren el tipo de algoritmo que estás buscando. Los que recuerdo son:

"Real-Time Embedded Systems" - Xiaocong Fan
"Embedded Systems Building Blocks" - Jean Labrosse

Podés buscar en la web bajo los términos: "Timing wheel C", "Timer wheel C" o "Software timers C". Hay muchas implementaciones dando vueltas.
Hay uno bastante interesante, que a diferencia del resto, está basado en eventos:



Saludos,
Fernando Mondello
El 10 de enero de 2017, 10:40, Geni Suarez<geni...@gmail.com> escribió:
Grcias Christian, pero vamos a intentarlo:

Realmente quisiera planificar algo muy básico para empezar por lo sencillo, más adelante ya incrementaría el nivel de complejidad.
Imaginemos 4 tareas o 5 a lo sumo; funciones que se ejecutan cuando son llamadas y está previsto que sean llamadas cuando ha pasado una cierta cantidad de tiempo (diferente en cada una) y que no son preventivas (no deben ser interrumpidas). Si me apuras a concretar un dato más, algunas pueden lanzar llamadas al driver, como sea leer o escribir en algún registro GPIO. 
Me gustaría saber cómo se escribe un planificador. Dónde y cómo se define, etc.. y bueno una estructura. Supongo que puedo tener un timer corriendo que al llegar a determinados valores active un flag. Luego fuera del timer ya comparo el flag (p ej: por polling) y si cambió entonces lanzo la tarea correspondiente. Así hasta que las n tareas hayan sido lanzadas de forma cíclica. Si alguna no puede lanzarse porque está en ejecución la anterior no pasa nada, ya saldrá cuando esté libre y le toque turno. 
Esa sería mi idea conceptual de lo que trataría de llevar a código.

Por cierto,  muy interesante ese link, lleva de todo.

--
-- Recibiste este mensaje porque estás suscripto al Grupo Google Embebidos32. Para postear en este grupo, escribe un email a embeb...@googlegroups.com. Para des-suscribirte, envía un email a embebidos32...@googlegroups.com. Para más opciones, visita el sitio del grupo en https://groups.google.com/d/forum/embebidos32?hl=es

---
Has recibido este mensaje porque estás suscrito al grupo "Embebidos32" de Grupos de Google.
Para cancelar la suscripción a este grupo y dejar de recibir sus mensajes, envía un correo electrónico a embebidos32...@googlegroups.com.

Para acceder a más opciones, visita https://groups.google.com/d/optout.



--
Saludos,
Fernando Mondello

martin ribelotta

unread,
Jan 10, 2017, 9:30:57 AM1/10/17
to embebidos32@
Voy a asumir que estas con cortex-m o algo asi, si no es el caso, mucha de la explicaciòn sirve pero se le quita la complegidad del cambio de contexto de los cortex-m.

Yo empesaria por lo mas simple, dos tareas que hagan poco y nada (sumar dos numeros, dejarlos en memoria, incrementar un contador, etc. cosas que puedas ver con un debugger)

Luego armas las estructuras del contexto del procesador (los registros a salvar, cuidado que en cortex-m algunos registros se salvan por la interrupción, con lo cual solo debes salvar los restantes)

En contraparte a lo que todos te recomiendan, yo dejaria el scheduler para el final, ya que es el tunning "fino", es decir, lo que hace que el OS ande mejor o peor.

El scheduling propiamente, es elegir una tarea de las posibles en ejecutar, lo mas simple para empezar, es tener un arreglo de tareas y ejecutarlas en secuencia a lo bruto, es decir:

// Tarea_t contiene el puntero al stack del procesador y
// eventualmente mas información de la tarea como el estado (lista, parada, esperando, terminada, etc)
// su prioridad o el tiempo que le queda para ejecutarse, pero como minimo, un puntero al stack.
typedef struct {
   unsigned int *stack;
} Tarea_t;

Tarea_t tareas[MAX_TAREAS];
int tarea_actual = 0;

Tarea_t *get_next_task() {
  // este es el scheduler mas simple e ineficiente del mundo, pero anda siempre
  // mas adelante, hay que cambiar el algoritmo para que ande bien el OS
  Tarea_t *t = tareas[tarea_actual];
  tarea_actual++;
  if (tarea_actual >= MAX_TAREAS)
    tarea_actual = 0;
  return t;
}


El 10 de enero de 2017, 10:40, Geni Suarez <geni...@gmail.com> escribió:
Grcias Christian, pero vamos a intentarlo:

Realmente quisiera planificar algo muy básico para empezar por lo sencillo, más adelante ya incrementaría el nivel de complejidad.
Imaginemos 4 tareas o 5 a lo sumo; funciones que se ejecutan cuando son llamadas y está previsto que sean llamadas cuando ha pasado una cierta cantidad de tiempo (diferente en cada una) y que no son preventivas (no deben ser interrumpidas). Si me apuras a concretar un dato más, algunas pueden lanzar llamadas al driver, como sea leer o escribir en algún registro GPIO. 

Finalmente, configurar un timer (Systick generalmente en cortex-m) que haga en guardado de la tarea, el cambio de contexto y la restauración de la misma.

Normalmente, eso se hace poniendo todos los registros en el stack, cambiando el stack pointer a la siguiente tarea y restaurando todos los registros del stack.

Por supuesto, para que esto funcione, las tareas tienen que inicializar el stack con su "contexto ya guardado", para que la interrupcion del timer la restaure correctamente la primera vez.

Particularmente, los ARMv7m (todos los cortex-m) tienen un cambio de contexto bastante "extraño" con respecto a todos los otros procesadores, porque una gran parte de este se hace por hardware.

Una muy detallada y didactica descripcion del cambio de contexto en cortex-m la podes encontrar aca:

En lo personal, me parece que el mecanismo de PendSV, es una complegidad innecesaria para arrancar, yo iniciaria con un simple task_save/task_restore dentro del Systick (configurado, por ejemplo, a 1ms)

void SysTick_Handler()  {
  asm volatile(
    "push {r4-r11,lr}\n" // solo salvamos r4-r11 y lr porque el resto ya lo salvo la interrupcion
    "bl get_next_task\n"
    "ldr r0, [r0]\n"  // r0 = Tarea_t->stack, solo que en ASM
    "msr msp, r0\n"  // Guardamos el retorno de la funcion en el stack actual.
    "pop {r4-r11,lr}\n"
  );
}

Esto lo unico que hace es cambiar la tarea dependiendo de lo que retorne get_next_task, en cortex-m esto trabaja mal con interrupciones de prioridad distinta y no tiene en cuenta las latencias, pero para empezar es un buen paso.

Lo siguiente en cortex-m seria mover el task switching a PendSV como aparece en los links de arriba.

Un buen lugar para empezar es el tutorial de Pablo Ridolfi en su github:

Te pase el link a uno de los primeros commits que son los mas simples, luego se mete con el contexto de la FPU, el lazy stack y otras cosas, por eso no tire directamente el master.

Otro OS "relativamente" simple es:
Que usa el mismo concepto que tiro aca de "calesita" de tareas sin importar ni su estado ni su prioridad.

Me gustaría saber cómo se escribe un planificador. Dónde y cómo se define, etc.. y bueno una estructura. Supongo que puedo tener un timer corriendo que al llegar a determinados valores active un flag. Luego fuera del timer ya comparo el flag (p ej: por polling) y si cambió entonces lanzo la tarea correspondiente. Así hasta que las n tareas hayan sido lanzadas de forma cíclica. Si alguna no puede lanzarse porque está en ejecución la anterior no pasa nada, ya saldrá cuando esté libre y le toque turno. 
Esa sería mi idea conceptual de lo que trataría de llevar a código.

En cuanto a schedulers, no puedo recomendarte mucho, lo que mas uso es round robin o planificación fija.

Round Robin, en su versión mas simple, es facil de implementar porque lo unico que requiere son dos variables, la prioridad de la tarea y un contador de ticks que le indique su prioridad actual. La tarea al pasar a lista, pone su contador de prioridad al valor de la prioridad configurada, y por cada tick la decrementa hasta llegar a cero, momento en que pasa a IDLE y se selecciona la siguiente tarea.

Luego se puede ampliar la cosa, con un flag de estado como:
 - lista para ejecutar: Tarea que al ser elegida, en la ronda de busqueda, pasa inmediatamente a ser seleccionada como la tarea a ejecutar
 - bloqueada: Tarea que esta a la espera de un evento, normalmente se agregan mas campos a la estructura Tarea_t para detectar si el evento ocurre y pasarla a "lista para ejecutar". La ronda de busqueda al encontrarla, simplemente pasa a la siguiente.
 - terminada: Tarea que no puede ser ejecutada mas, lo mismo que la anterior, se pasa a la siguiente.

Como veraz, la siguiente gran mejora es tener, en vez de un array, una lista enlazada que se vaya creando dinamicamente, entonces, las tareas listas para ejecutar tienen su propia lista, las bloqueadas las suyas y las terminadas no van a ninguna lista.

Si nos vamos a "lo que yo prefiero" en schedulers, estoy trabajando bastante con los cheduler deadline, que basicamente proclaman que la tarea debe especificar cuanto tiempo de procesador quiere garantizado, cada cuanto quiere ser planificada y cuanto es lo maximo que piensa tardar.

La referencia mas "human readable" que encuentro es la del EDF de Linux:

Que basicamente es elegir la mas cercana (por eso la E de Early) en tiempo a ser planificada.

Este scheduler es ideal para sistemas criticos porque permite darle un grado de severidad a los fallos de tiempos y delega en diseño no tanto en la inteligencia del scheduler sino en los requerimientos del programador (que los debe tener en claro)

Por otro lado, todos los cheduler deadline se me antojan bastante dificiles de implementar bien, pero een su forma basica, es mantener el tiempo de arrivo y partida de cada tarea, calculandolo en la salida de la tarea del procesador.
 
Por cierto,  muy interesante ese link, lleva de todo.

--
-- Recibiste este mensaje porque estás suscripto al Grupo Google Embebidos32. Para postear en este grupo, escribe un email a embeb...@googlegroups.com. Para des-suscribirte, envía un email a embebidos32+unsubscribe@googlegroups.com. Para más opciones, visita el sitio del grupo en https://groups.google.com/d/forum/embebidos32?hl=es

---
Has recibido este mensaje porque estás suscrito al grupo "Embebidos32" de Grupos de Google.
Para cancelar la suscripción a este grupo y dejar de recibir sus mensajes, envía un correo electrónico a embebidos32+unsubscribe@googlegroups.com.

Geni Suarez

unread,
Jan 10, 2017, 9:43:48 AM1/10/17
to Embebidos32
Franco muchas gracias por el aporte :)

Geni Suarez

unread,
Jan 10, 2017, 11:22:48 AM1/10/17
to Embebidos32
Gracias Martín por las molestias en la elaboración de tu respuesta, sólo creo que puedo añadir que me parece que no necesito guardar el contexto. Dado que sólo voy a ejecutar las tareas si cuando llega su hora de ejecutarse la tarea anterior terminó. Tengo prevista la duración aprox de cada tarea para el valor del timer que activará la tarea en cuestión. Si por lo que sea una tarea se alarga en tiempo o alguna vez no se puede ejecutar una tarea simplemente se pierde por una vez. Al menos así de "estricto" mi primer plan pretendo que sea.

Tomo todos tus consejos en cuenta para los casos de cambio de contexto. 

SAludos!

--
-- Recibiste este mensaje porque estás suscripto al Grupo Google Embebidos32. Para postear en este grupo, escribe un email a embeb...@googlegroups.com. Para des-suscribirte, envía un email a embebidos32...@googlegroups.com. Para más opciones, visita el sitio del grupo en https://groups.google.com/d/forum/embebidos32?hl=es

---
Has recibido este mensaje porque estás suscrito al grupo "Embebidos32" de Grupos de Google.
Para cancelar la suscripción a este grupo y dejar de recibir sus mensajes, envía un correo electrónico a embebidos32...@googlegroups.com.

Christian N

unread,
Jan 10, 2017, 12:38:54 PM1/10/17
to Embebidos32
Hola nuevamente

Coincidiendo con lo dicho por Martin y un poco lo que intente comentar en la primer respuesta, el algoritmo de scheduling es lo menos importante por lo menos al comenzar ya que de nada sirve si no se domina la arquitectura donde se implementara.

Tomando tu decision de conmutar las tareas cuando finalizan, eso mas que preemtivo (como indicaste originalmente) seria algo mas parecido a colaborativo.
Pasando en limpio tu especificacion, que dista de ser colaborative, preemtive u orientada eventos, pareceria que tu idea es que un temporizador dispara la conmutacion de tarea cada un tiempo N. Dicho tiempo sera el que tenga asignado la tarea para hacer su mision. En este contexto ni bien sepas que procesador utilizar, o aunque sea que arquitectura vas a emplear tenes que reconocer como vas a restaurar los registros de la interrupcion del temporizador. Pensando en voz alta, suponiendo que estamos en la tarea 1 (al fin y al cabo por una hay que empezar aunque sea la idle), salta la interrupcion, segun la arquitectura los datos de retorno se almacenan en la pila o en registros especificos (retene esto en mente), ahora dentro del controlador de la interrupcion vos modificas dichos registros para que cuando hagas el iret, reti (o como sea en el uP) la direccion de salto sea el comienzo de la siguiente tarea.
Con este escenario ya tenes bastante para pensar, ¿donde esta guardadas las direcciones de inicio de la siguiente tarea? ¿cuando te referis que se perdio por una vez, donde guardaste los registros para retomar su ejecucion la proxima vez que se ejecute? ¿en que nivel de ejecucion esta la rutina de conmutacion? ¿que sistemas de proteccion tiene la arquitectura/uP? ¿quien inicializo los registros de gestion de memoria paginacion/segmentacion o lo que sea.
Por ejemplo en Intel (x86/64) podes conmutar de una tarea a otra sin necesidad de timer, el procesador tiene mecanismos de anidamiento y conmutacion internos que te facilitan la tarea, basta que al finalizar cada tarea haga una jmp far o call a una estructura especfica de la arquitectura que se encarga de activar el mecanismo de guardado y restaurado del contexto. Por lejos este metodo es el menos utilizado ya que es super dependiente de esta arquitectura, pero bastante facil de llevar adelante.

Realmente empezar por el algoritmo de scheduling sin saber la arquitectura que lo va a soportar no es mas que un mero ejercicio de listas enlazadas, ya que lo complejo del scheduler es su gestion de cambio de contexto. Al menos es el consejo desde mi humilde experiencia.

Salu2

martin ribelotta

unread,
Jan 10, 2017, 1:18:53 PM1/10/17
to embebidos32@
Va entre lineas

El 10 de enero de 2017, 14:38, Christian N <cneg...@gmail.com> escribió:
Hola nuevamente

Coincidiendo con lo dicho por Martin y un poco lo que intente comentar en la primer respuesta, el algoritmo de scheduling es lo menos importante por lo menos al comenzar ya que de nada sirve si no se domina la arquitectura donde se implementara.

Tomando tu decision de conmutar las tareas cuando finalizan, eso mas que preemtivo (como indicaste originalmente) seria algo mas parecido a colaborativo.
Pasando en limpio tu especificacion, que dista de ser colaborative, preemtive u orientada eventos, pareceria que tu idea es que un temporizador dispara la conmutacion de tarea cada un tiempo N. Dicho tiempo sera el que tenga asignado la tarea para hacer su mision. En este contexto ni bien sepas que procesador utilizar, o aunque sea que arquitectura vas a emplear tenes que reconocer como vas a restaurar los registros de la interrupcion del temporizador. Pensando en voz alta, suponiendo que estamos en la tarea 1 (al fin y al cabo por una hay que empezar aunque sea la idle), salta la interrupcion, segun la arquitectura los datos de retorno se almacenan en la pila o en registros especificos (retene esto en mente), ahora dentro del controlador de la interrupcion vos modificas dichos registros para que cuando hagas el iret, reti (o como sea en el uP) la direccion de salto sea el comienzo de la siguiente tarea.

Creo que lo que Geni necesita, se puede implementar bastante facil en (casi totalmente) C.

Me explico, ella va a tener una lista de tareas (ya sea en array o en una lista enlazada) con un periodo de activación predefinido (algo asi como un deadline) y una duración predefinidas.

Asi que podria funcionar algo como esto:
typedef struct {
  void (*entry)();
  uint32_t timestamp;
  uint32_t duration;
  uint32_t interval;
} Task_t;

extern Task_t *get_next_task(); // scheduler propiamente dicho
extern uint32_t current_time(); // retorna el timestamp actual (en ticks, ms, us o lo que fuere)
extern void ConfigTimer(uint32_t duration); // Configura interrupcion del timer para duration (ticks, ms, us o lo que fuere)
extern void ResetTimer(); // deshabilita la interrupcion del timer

// Contexto para volver de la tarea cuando se supera el tiempo de ejecución
jmp_buf tout_ctx;

void sched() {
  while(1) {
    Task_t *t = get_next_task();
    uint32_t ts = current_time();
    if (t->timestamp >= ts && t->timestamp <= ts + t->duration) {
      if (setjmp(&tout_ctx) == 0) {
        t->entry();
        ResetTimer();
      } else {
        printf("Task %p timeout", t);
      }
    }
    t->timestamp = ts + t->interval;
  }
}

// TimerInterrupt es llamada cada vez que termina la cuenta del timer
void TimerInterrupt() {
  // Restaura el contexto salvado antes de entrar a la tarea
  longjmp(tout_ctx);
  // Esto es incorrecto y puede fallar si esta en una interrupción
  // Hay que implementarlo manipulando el stack de interrupción
}
Por supuesto que setjmp y longjmp no funcionan entre medio de las interrupciones, pero es factible armar una implementaciòn que si lo haga.
Tambien es muy mejorable el mecanismo de selección de tareas (tomo como que get_next_task() devuelve la siguiente tarea en la lista enlazada/array sin hacer ningun timpo de scheduling)

Con este escenario ya tenes bastante para pensar, ¿donde esta guardadas las direcciones de inicio de la siguiente tarea? ¿cuando te referis que se perdio por una vez, donde guardaste los registros para retomar su ejecucion la proxima vez que se ejecute? ¿en que nivel de ejecucion esta la rutina de conmutacion? ¿que sistemas de proteccion tiene la arquitectura/uP? ¿quien inicializo los registros de gestion de memoria paginacion/segmentacion o lo que sea.

En ppio con este esquema, no tendria las complicaciones tipicas de un task switcher comun y corriente, aparte de que seria portable entre otras muchas arquitecturas con un minimo de area dependiente de la arquitectura.
 
Por ejemplo en Intel (x86/64) podes conmutar de una tarea a otra sin necesidad de timer, el procesador tiene mecanismos de anidamiento y conmutacion internos que te facilitan la tarea, basta que al finalizar cada tarea haga una jmp far o call a una estructura especfica de la arquitectura que se encarga de activar el mecanismo de guardado y restaurado del contexto. Por lejos este metodo es el menos utilizado ya que es super dependiente de esta arquitectura, pero bastante facil de llevar adelante.

Si algo detesto es el task descriptor de los x86 (no se si en ia64 lo siguen manteniendo) pero en su momento me fue imposible hacerlo andar de forma estable sin que explotara todo al tercer salto (posiblemente por mi incompetencia y mis apuros para verlo andando) pero ahí aprendi que x86 es una arquitectura roñosa como ella sola, parece que hubieran tirado varios libros de sistemas operativos a una batidora, la hubieran encendido y con lo que quedó hicieron el datasheet del i386
 
Realmente empezar por el algoritmo de scheduling sin saber la arquitectura que lo va a soportar no es mas que un mero ejercicio de listas enlazadas, ya que lo complejo del scheduler es su gestion de cambio de contexto. Al menos es el consejo desde mi humilde experiencia.

Salu2

--
-- Recibiste este mensaje porque estás suscripto al Grupo Google Embebidos32. Para postear en este grupo, escribe un email a embeb...@googlegroups.com. Para des-suscribirte, envía un email a embebidos32+unsubscribe@googlegroups.com. Para más opciones, visita el sitio del grupo en https://groups.google.com/d/forum/embebidos32?hl=es

---
Has recibido este mensaje porque estás suscrito al grupo "Embebidos32" de Grupos de Google.
Para cancelar la suscripción a este grupo y dejar de recibir sus mensajes, envía un correo electrónico a embebidos32+unsubscribe@googlegroups.com.

Geni Suarez

unread,
Jan 11, 2017, 6:43:04 AM1/11/17
to Embebidos32
Te agradezco Cristian el comentario, pero creo que no dije que era preventivo, sino todo lo contrario. Lamento haberte hecho confundir si me dejé alguna palabra o pareció que dije eso. Y sobre el grado de "estricto" de mi sistema me refiero a que de momento si alguna tarea en uno de los ciclos no ha podido ocupar la CPU no me importaría. Sólo por un punto de partida, para empezar. 
Otra pregunta trascendental para mí es que para llamar al scheduler e implementarlo en C (sin RTOS ni OS en el micro) me imagino que debería incluir algunos archivos o librerías. Cuáles?

Christian N

unread,
Jan 11, 2017, 7:10:33 AM1/11/17
to Embebidos32
No debes utilizar ningun tipo de biblioteca, al menos no si comenzas bare metal.
Observa en la buen primer ensayo que envio Martin la implementacion es C puro sin bibliotecas, al igual que el del enlace que envio Fernando.
¿Sabes sobre que uP lo vas a realizar?, asi es mas facil guiarte con los pasos y herramientas disponibles

Geni Suarez

unread,
Jan 11, 2017, 7:56:53 AM1/11/17
to Embebidos32
Grcias chicos, creo que por ahora tengo suficiente material para estudiar, pensar y practicar. Tengo fe en que gracias a vuestros consejos y sugerencias voy a lograr obtener al fin un sencillo scheduler. 

Me acaban de pasar una placa para integrar los drivers del fabricante y arrancar cosas en ella, así que creo llevarlo a cabo el scheduler en esta misma plataforma estaría bien, es un ARM c-M4 de ST (para la STM32L476).

Saludos

Eric Pernia

unread,
Jan 11, 2017, 8:53:43 AM1/11/17
to Embebidos32
Buen día, para algo tan sencillo me sumo a lo de Franco con el libro de M. J. Pont (lo aplica sobre 8051) que son todos schedulers cooperativos (sin cambio de contexto),

En el repo nuevo de la CIAA que estamos trabajando junto a Martín R:

https://github.com/ciaa/firmware_v2

Puse estos 2 ejemplos (ambos del libro de Pont):

https://github.com/ciaa/firmware_v2/tree/master/sapi_examples/edu-ciaa-nxp/sapi_os_01_seos

https://github.com/ciaa/firmware_v2/tree/master/sapi_examples/edu-ciaa-nxp/sapi_os_02_seos_bakground_foreground

Y acá la ayuda de lo que hacen:

https://github.com/ciaa/firmware_v2/blob/master/sapi_examples/documentation/docs/ejemplos.md

Ambos hechos totalmente en C. Vas a ver que nombra existe un tercer ejemplo que no está en el repo nuevo pero podés verlo acá:

https://github.com/epernia/sAPI/archive/v0.3.0.zip

Que es el ejemplo más completo pero me falta portarlo a la nueva versión de la biblioteca sAPI.

Lo único que necesitás para portarlo a tu micro es ver como poner a interrumpir un timer en forma periódica y luego el resto de hardware que necesites. En el micro que tenés seguramente tenga SysTick Timer para la interrupción periódica.

Luego en este link están las filiminas de clases  que uso para dar esos temas:

https://sites.google.com/site/programaciondemicros/home/CalendarioyTeoricas

Saludos.
Eric.

Matias Vara

unread,
Jan 12, 2017, 11:30:18 AM1/12/17
to embeb...@googlegroups.com
Hola, mi scheduler lo tengo implementado casi todo en freepascal lo cual facilita la lectura del código. Podes encontrarlo en https://sourceforge.net/p/toro/code/ci/master/tree/rtl/Process.pas , linea  877. El scheduler también implementa migración threads entre diferente procesadores, esa es la parte mas entretenida ;) 

Saludos, Matias

--
-- Recibiste este mensaje porque estás suscripto al Grupo Google Embebidos32. Para postear en este grupo, escribe un email a embeb...@googlegroups.com. Para des-suscribirte, envía un email a embebidos32+unsubscribe@googlegroups.com. Para más opciones, visita el sitio del grupo en https://groups.google.com/d/forum/embebidos32?hl=es

---
Has recibido este mensaje porque estás suscrito al grupo "Embebidos32" de Grupos de Google.
Para cancelar la suscripción a este grupo y dejar de recibir sus mensajes, envía un correo electrónico a embebidos32+unsubscribe@googlegroups.com.

Christian N

unread,
Jan 12, 2017, 12:17:36 PM1/12/17
to Embebidos32
Cha man!!! Que laburazo!!!!!!!!!!!!!!!
Mire los fuentes y estan grosos!

--
-- Recibiste este mensaje porque estás suscripto al Grupo Google Embebidos32. Para postear en este grupo, escribe un email a embeb...@googlegroups.com. Para des-suscribirte, envía un email a embebidos32...@googlegroups.com. Para más opciones, visita el sitio del grupo en https://groups.google.com/d/forum/embebidos32?hl=es

---
Has recibido este mensaje porque estás suscrito al grupo "Embebidos32" de Grupos de Google.
Para cancelar la suscripción a este grupo y dejar de recibir sus mensajes, envía un correo electrónico a embebidos32...@googlegroups.com.

Matias Vara

unread,
Jan 12, 2017, 12:29:07 PM1/12/17
to embeb...@googlegroups.com
Ese es un scheduler cooperativo. También implemente una especie de RR y FIFO en https://github.com/MatiasVara/ToroOS/blob/master/usr/src/procesos/scheduler.pas pero este es otro OS, con diferente propósito. El código es bastante agradable a la lectura. Tal vez te de algunas ideas. 
Reply all
Reply to author
Forward
0 new messages