01 · Punto de partida
La pregunta de fondo: quién decide qué corre
Un procesador ejecuta una instrucción a la vez, pero un producto real tiene que hacer varias cosas «al mismo tiempo»: leer un sensor, atender un botón, refrescar una pantalla, hablar por el puerto serie. Todas las arquitecturas de software de un sistema embebido son respuestas distintas a una misma pregunta: ¿quién decide qué código se ejecuta en cada momento, y qué pasa cuando llegan varias cosas a la vez?
En una computadora de escritorio, esa decisión la toma el sistema operativo y vos no te enterás. En un microcontrolador, muchas veces la tomás vos, con tu propio código, y eso tiene dos caras: dominás exactamente qué corre y cuándo, pero también heredás la responsabilidad de que nada se bloquee ni se pierda.
Este tema es un mapa: presenta cada arquitectura y deja claro cuándo usarla. Los detalles (interrupciones, temporizadores, planificadores, RTOS) se desarrollan uno por uno en el bloque de tiempo real, del tema 13 en adelante.
02 · Organización interna
Las capas de un firmware
Antes de ver cómo se reparte el tiempo, conviene ver cómo se reparte el código. Un firmware bien organizado se divide en capas, cada una con una responsabilidad. Una de arriba solo conoce a la de abajo, igual que en el modelo de capas de las comunicaciones:
| Capa | Responsabilidad | Ejemplo |
|---|---|---|
| Aplicación | La lógica del producto: qué hace y cuándo | «Si la temperatura baja de la consigna, encender el calefactor» |
| Servicios y bibliotecas | Funciones reutilizables independientes del chip | Pila de comunicaciones, sistema de archivos, controladores de tipo PID, análisis de comandos |
| Drivers de dispositivo | Manejan un componente concreto | Driver del sensor de temperatura, de la pantalla, del módem |
| Capa de abstracción de hardware (HAL) | Interfaz común para los periféricos del chip | gpio_escribir(), uart_enviar() |
| Hardware | Registros y periféricos del microcontrolador | Los registros del tema anterior |
La ventaja de este orden es el cambio localizado: si el fabricante saca un chip nuevo, solo se reescribe la capa de abajo; si cambia el sensor, solo su driver. La lógica de la aplicación, que es lo que más vale, queda intacta. Esta separación (tema 10 y 11) es independiente de la arquitectura de tiempo: se aplica igual con un superloop que con Linux.
Además de las capas, hay un componente transversal: el planificador (scheduler), que decide el orden de ejecución. Su presencia y su forma son justamente lo que distingue a las arquitecturas que siguen.
03 · La más simple
Bare-metal con superloop
Se llama bare-metal («metal desnudo») a programar directamente sobre el hardware, sin sistema operativo. La forma más simple de organizar ese programa es el superloop, que viste en el tema 1: se inicializa todo y luego un bucle infinito recorre las tareas en orden, una tras otra.
int main(void) {
hardware_init();
while (1) {
if (boton_presionado()) { // 1) ¿hay que atender el botón?
atender_boton();
}
leer_sensor_y_actualizar_pantalla(); // 2) tarea lenta: unos 50 ms
enviar_datos_si_corresponde(); // 3) comunicaciones
}
}
Cada vuelta del bucle consulta si hay algo que hacer (polling) y lo hace. Es la arquitectura de cientos de millones de productos, y no es casualidad: es fácil de entender, fácil de depurar (el flujo es lineal y reproducible), consume la mínima memoria y no necesita ningún componente de terceros.
Su límite está en el tiempo. Mirá el ejemplo: si la tarea 2 tarda 50 ms, el botón solo se consulta una vez cada 50 ms o más. La respuesta a un evento puede demorar, en el peor caso, lo que dura una vuelta completa del bucle:
Y peor: si el evento es corto (un pulso de pocos milisegundos), puede ocurrir y terminar mientras el programa estaba ocupado con la tarea lenta, y nunca llegar a verse. Cualquier función que bloquee (una espera con delay(), un bucle que espera un dato) frena todo lo demás. Por eso, en un superloop, cada tarea debe ser corta y no bloqueante: terminar rápido y dejar su estado guardado para continuar en la próxima vuelta.
Cuándo conviene: productos simples, con pocas funciones, plazos holgados (cientos de milisegundos) y recursos mínimos: una cerradura, un control remoto, un termostato, un sensor que mide y duerme.
04 · Primer plano y segundo plano
Superloop con interrupciones
Cuando el polling no alcanza, el siguiente paso casi universal es agregar interrupciones. Una interrupción es una señal del hardware (un pin que cambia, un temporizador que vence, un byte que llega) que hace que el procesador suspenda lo que estaba haciendo, ejecute una rutina corta llamada ISR y luego retome exactamente donde estaba. Así, el evento urgente se atiende en microsegundos sin esperar al bucle.
El resultado se llama arquitectura de primer plano y segundo plano (foreground/background): las ISR son el primer plano y atienden lo urgente; el bucle principal es el segundo plano y hace lo demás. Un patrón muy usado es que la ISR haga lo mínimo y deje una bandera para que el bucle haga el trabajo largo:
volatile uint8_t hay_pulso = 0; // lo comparten la ISR y el bucle
void EXTI0_IRQHandler(void) { // ISR: se ejecuta sola al llegar el pulso
limpiar_aviso_de_interrupcion();
hay_pulso = 1; // solo avisa: rápido y corto
}
int main(void) {
hardware_init();
while (1) {
if (hay_pulso) { // el bucle atiende el aviso cuando puede
hay_pulso = 0;
atender_pulso();
}
tarea_lenta(); // sigue tardando lo que tarda
}
}
Hay una trampa sutil. Con este esquema, el aviso es inmediato pero la atención no: el bucle recién mira la bandera cuando termina la tarea lenta. Si el trabajo debe hacerse en pocos microsegundos, hay que hacerlo dentro de la propia ISR. Pero entonces todo lo que se haga allí bloquea al resto, y además aparecen problemas nuevos: variables compartidas entre la ISR y el bucle (por eso volatile), datos a medias, banderas de un solo bit que pierden eventos si llegan dos seguidos. Estudiaremos cómo manejarlo bien en los temas 15 y 16.
Cuándo conviene: productos con uno o pocos eventos urgentes (comunicaciones, un sensor de pulsos, un control en lazo cerrado) y lógica simple, que quieren seguir sin sistema operativo. Es la arquitectura más frecuente en productos de producción masiva.
05 · Un paso más de orden
Planificación cooperativa y por eventos
Cuando el bucle crece, mantener el orden «a mano» se complica. Una evolución natural, todavía sin sistema operativo, es la planificación cooperativa: cada tarea es una función corta que se ejecuta cuando le toca, y un pequeño planificador decide cuándo, normalmente a partir de un temporizador que marca el «tick» del sistema:
- La tarea A corre cada 10 ms, la B cada 100 ms, la C cada segundo.
- Las tareas cooperan: cada una debe terminar rápido y devolver el control. Si una se queda más de la cuenta, atrasa a las demás.
- Una tarea nunca interrumpe a otra: solo las ISR interrumpen. Eso simplifica mucho las variables compartidas.
Una variante muy potente es la programación orientada a eventos: el programa es una máquina de estados que reacciona a eventos (botón, tiempo, mensaje) que llegan por una cola. En lugar de «preguntar» continuamente, el sistema espera y duerme hasta que algo pasa. Combina bien con el bajo consumo (el procesador duerme cuando la cola está vacía). Veremos ambas ideas en los temas 19 y 26.
Los límites de la cooperación son claros: una tarea larga no se puede desalojar. Para una tarea de 50 ms, no hay manera de que otra más urgente la interrumpa a mitad de camino salvo una ISR. Para eso hace falta un planificador que pueda desalojar, que es lo que ofrece un sistema operativo de tiempo real.
06 · Planificador con prioridades
Sistema operativo de tiempo real
Un RTOS (Real-Time Operating System) es un núcleo pequeño que reparte el procesador entre varias tareas, cada una escrita como si tuviera el procesador para ella sola, con su propio bucle infinito y su propia pila. Lo distintivo es que es expulsivo (preemptive): cada tarea tiene una prioridad y, si despierta una de prioridad mayor, el planificador interrumpe a la que corría y le cede el procesador de inmediato, sin esperar a que termine.
SemaphoreHandle_t sem_evento;
void tarea_urgente(void *param) { // prioridad alta
for (;;) {
xSemaphoreTake(sem_evento, portMAX_DELAY); // duerme hasta que llegue el evento
atender_evento();
}
}
void tarea_lenta(void *param) { // prioridad baja
for (;;) {
leer_sensor_y_actualizar_pantalla(); // puede ser interrumpida en cualquier momento
vTaskDelay(pdMS_TO_TICKS(100)); // cede el procesador 100 ms
}
}
void EXTI0_IRQHandler(void) { // la ISR solo despierta a la tarea urgente
BaseType_t despertar = pdFALSE;
xSemaphoreGiveFromISR(sem_evento, &despertar);
portYIELD_FROM_ISR(despertar);
}
int main(void) {
hardware_init();
sem_evento = xSemaphoreCreateBinary();
xTaskCreate(tarea_urgente, "urgente", 256, NULL, 3, NULL);
xTaskCreate(tarea_lenta, "lenta", 256, NULL, 1, NULL);
vTaskStartScheduler(); // nunca retorna
}
El ejemplo usa FreeRTOS, el RTOS más difundido, pero la estructura es la misma en todos. Fijate en el cambio de forma de pensar: el programa deja de ser un bucle y pasa a ser varios programas pequeños, cada uno enfocado en un asunto. La tarea urgente se bloquea esperando el evento y no gasta procesador; la lenta ya no tiene que «dejar libre» el bucle, porque la interrumpen cuando hace falta.
Un RTOS ofrece, además de la planificación, las herramientas para que las tareas se comuniquen y se coordinen: colas de mensajes, semáforos, mutex y temporizadores por software (temas 21 y 22). A cambio, tiene un precio:
- Memoria. El núcleo suma unos 5 a 10 KB de flash y algo de RAM; además, cada tarea necesita su propia pila, que hay que dimensionar con cuidado (una pila chica corrompe la memoria; una grande desperdicia RAM).
- Tiempo. Cada cambio de contexto y cada «tick» consumen unos microsegundos de procesador.
- Complejidad. Aparecen errores nuevos y difíciles: condiciones de carrera, inversión de prioridad, interbloqueos (tema 22). Un RTOS bien usado simplifica el diseño; mal usado lo complica.
Cuándo conviene: productos con varias funciones independientes y plazos distintos, con comunicaciones (pila de red, USB, Bluetooth) o una lógica que crece con el tiempo. En microcontroladores con 32 KB de RAM o más, es hoy la opción más frecuente cuando el superloop se queda corto.
07 · El extremo de la escala
Linux embebido
En el otro extremo está Linux embebido: un sistema operativo completo, el mismo núcleo que corre en los servidores, adaptado a un dispositivo. Ofrece procesos con memoria protegida, sistemas de archivos, redes completas, USB, pantallas gráficas, miles de bibliotecas y lenguajes como Python. Un router, un televisor, una cámara IP o el tablero de un auto suelen funcionar así.
Pero necesita otro tipo de procesador: uno con unidad de gestión de memoria (MMU), que casi siempre es un procesador de aplicaciones (los Cortex-A) con memoria externa. Sus costos son los inversos a los del superloop:
- Recursos. Decenas de megabytes de RAM y de almacenamiento como mínimo, memoria externa y una placa más compleja.
- Arranque. De varios segundos, aunque con mucha optimización puede bajarse a fracciones de segundo.
- Consumo. Vatios en lugar de microvatios; no sirve para dispositivos que deben durar años con una pila.
- Tiempo real. El núcleo estándar no garantiza plazos. Con el parche
PREEMPT_RTmejora mucho, pero sigue siendo más difícil de garantizar que un RTOS pequeño. - Apagado y fallas. Un corte de energía en medio de una escritura puede corromper el sistema de archivos, y el mantenimiento de un sistema de ese tamaño (actualizaciones, seguridad) es un trabajo en sí mismo.
Por eso muchos productos complejos son híbridos: un procesador con Linux se encarga de la interfaz, la red y el almacenamiento, y un microcontrolador con RTOS o bare-metal atiende lo que exige tiempo real o bajo consumo (motores, sensores, seguridad). Se comunican por un bus serie. Cada uno hace lo que mejor sabe.
08 · Elegir
Comparación y cómo elegir
| Criterio | Superloop | Superloop con interrupciones | RTOS | Linux embebido |
|---|---|---|---|---|
| Memoria mínima | Kilobytes | Kilobytes | Núcleo de 5 a 10 KB de flash y 1 a 4 KB de RAM más las pilas | Decenas de MB de RAM y de almacenamiento |
| Latencia de respuesta | Hasta una vuelta del bucle | Muy baja en la ISR; el resto espera | Baja y acotada para tareas de alta prioridad | Mayor y menos predecible |
| Concurrencia | Ninguna | ISR más el bucle | Muchas tareas con prioridades | Procesos e hilos con memoria protegida |
| Red, USB, archivos, pantallas | A mano | A mano | Con bibliotecas | Incluidos |
| Consumo | Mínimo | Mínimo | Bajo | Alto |
| Arranque | Milisegundos | Milisegundos | Milisegundos | Segundos |
| Dificultad de depurar | Baja | Media (carreras con las ISR) | Media a alta | Alta, con otras herramientas |
| Certificación de seguridad | Más sencilla | Media | Existen RTOS certificados | Difícil |
No hay una arquitectura «mejor»: es un menú con precios. Una forma práctica de decidir es subir por la escalera solo hasta donde haga falta:
- Si el producto es simple y los plazos son holgados, superloop.
- Si hay uno o dos eventos urgentes, agregá interrupciones.
- Si las funciones se multiplican, los plazos son distintos o hay una pila de comunicaciones pesada, pasá a un RTOS.
- Si necesitás un sistema de archivos completo, interfaz gráfica compleja, muchas bibliotecas o redes avanzadas, y el presupuesto de energía y costo lo permite, usá Linux (a menudo junto a un microcontrolador que se ocupa del tiempo real).
Cada escalón agrega capacidad y también complejidad. Una buena regla de ingeniería es la misma del tema 2: la arquitectura más simple que cumple los requisitos con margen. Y recordá que migrar después (de superloop a RTOS, por ejemplo) es posible pero cuesta reescribir mucho; conviene decidirlo con visión de la evolución del producto.
09 · Analogía con programación
Medir la latencia en Python
Para sentir la diferencia entre arquitecturas sin hardware, este programa simula diez segundos de un dispositivo que hace una tarea lenta y debe reaccionar a un evento urgente que dura 5 ms y llega cada cierto período. Mide, para cada arquitectura, cuántos eventos se atienden y cuánto demora la respuesta. Los tiempos están en milisegundos.
Python en tu navegador. Los bloques son editables: cambiá los valores y presioná «Ejecutar Python». La primera vez tarda unos segundos en cargar.
DURACION = 10000 # ms simulados
FASE = 3.7 # instante del primer evento
ANCHO_PULSO = 5 # ms que dura la señal del evento
T_ATENCION = 0.5 # ms de trabajo para responder
T_SONDEO = 0.1 # ms que cuesta mirar si hubo evento en cada vuelta
T_ISR = 0.02 # ms hasta entrar en la ISR
T_CAMBIO = 0.05 # ms de cambio de contexto en un RTOS
TAREA_MS = 50 # duración de la tarea lenta
PERIODO_MS = 100 # cada cuánto llega un evento urgente
def simular(arquitectura):
eventos = []
t = FASE
while t < DURACION:
eventos.append(t)
t += PERIODO_MS
latencias = []
examinados = len(eventos)
if arquitectura in ("isr", "rtos"):
base = T_ISR if arquitectura == "isr" else T_CAMBIO
latencias = [base + T_ATENCION for _ in eventos]
else:
t, i = 0.0, 0
while t < DURACION:
t += TAREA_MS # la tarea lenta ocupa el procesador
pendientes = []
while i < len(eventos) and eventos[i] <= t:
pendientes.append(eventos[i])
i += 1
if arquitectura == "polling": # solo se ve si la señal sigue activa
for te in pendientes:
if t < te + ANCHO_PULSO:
latencias.append(t - te + T_ATENCION)
t += T_ATENCION
elif pendientes: # bandera de un bit: queda el último
te = pendientes[-1]
latencias.append(t - te + T_ATENCION)
t += T_ATENCION
t += T_SONDEO
examinados = i
return examinados, latencias
NOMBRES = {
"polling": "Superloop (polling)",
"bandera": "Superloop + bandera de ISR",
"isr": "Superloop + ISR que responde",
"rtos": "RTOS (tarea de alta prioridad)",
}
for clave, nombre in NOMBRES.items():
total, lat = simular(clave)
media = sum(lat) / max(1, len(lat))
print(f"{nombre:30s} {len(lat):3d}/{total} atendidos media {media:6.2f} ms máx {max(lat, default=0):6.2f} ms")
Resultado con una tarea de 50 ms y eventos cada 100 ms: el superloop con polling atiende apenas 7 de 100 eventos (el pulso de 5 ms casi siempre ocurre mientras el bucle está ocupado). Con bandera de ISR se atienden los 100, pero con una media de 22,83 ms y un máximo de 50,30 ms: el aviso es instantáneo y la atención espera a que termine la tarea lenta. Con la ISR que responde, la latencia es de 0,52 ms constantes; con el RTOS, 0,55 ms. Probá TAREA_MS = 2: hasta el polling atiende todo. Probá PERIODO_MS = 25 con la bandera: llegan varios eventos entre dos vueltas y se pierden más de la mitad.
Observá que en las dos últimas arquitecturas la latencia no depende de cuánto tarda la tarea lenta. Eso es lo que compra la interrupción: independizar el tiempo de respuesta del resto del programa. La diferencia entre ellas (0,52 contra 0,55 ms) es el costo del cambio de contexto, ínfimo frente a lo que ahorra en este caso.
10 · Exploración interactiva
¿Qué tan rápido responde?
El laboratorio ejecuta la misma simulación del apartado anterior durante diez segundos y te deja variar la arquitectura, la duración de la tarea lenta y el período del evento urgente. Elegí también el plazo que exige el producto: el veredicto compara el peor caso medido con ese plazo, y exige que no se pierda ningún evento. También se informa el costo de memoria aproximado de cada arquitectura.
Tarea lenta, evento urgente y arquitectura
Cambiá cualquier opción para ver cómo responde el sistema.
Recorrido guiado
- Con los valores iniciales (polling, tarea de 50 ms), apenas se atienden 7 de 100 eventos. El problema no es la lentitud sino la ceguera: el sistema ni se entera de los que ocurren mientras está ocupado.
- Bajá la tarea a 2 ms. El polling atiende los 100 eventos y la latencia máxima es de 2,6 ms. Con tareas cortas, la arquitectura más simple alcanza.
- Con 10 ms, el polling atiende 46 de 100. Cambiá a «bandera de ISR»: ahora se atienden los 100, pero la respuesta espera hasta 10,6 ms.
- Con la tarea de 50 ms y la bandera, no se pierde nada a 100 ms, pero la latencia máxima es de 50,3 ms y supera el plazo de 20 ms. Poné el evento cada 25 ms: ahora la bandera pierde la mitad de los eventos.
- Pasá a «ISR que responde»: la latencia es de 0,52 ms sin importar la tarea ni el período. Hacés el trabajo dentro de la interrupción, a cambio de bloquear a todo lo demás durante ese tiempo.
- Pasá a RTOS: 0,55 ms, con la misma independencia, pero con la memoria extra que indica el panel y la posibilidad de tener muchas tareas.
- Bajá el plazo a 1 ms y recorré las cuatro arquitecturas con la tarea de 200 ms. Solo las dos últimas cumplen.
Desafío: ¿por qué 0,52 ms y no 0,02?
El 0,02 ms es lo que tarda el hardware en entrar a la ISR; los 0,5 ms restantes son el trabajo real de responder al evento. Es una distinción importante: la latencia de interrupción (cuánto tarda en empezar a atenderse) es de microsegundos, pero el tiempo de respuesta incluye todo lo que hay que hacer. Si ese trabajo es largo, no debe hacerse en la ISR: se deja una bandera o se despierta una tarea. Esa es la tensión de diseño que resuelven el RTOS y las colas de eventos.
11 · Método de trabajo
Método para elegir la arquitectura
Seguí estas preguntas en orden. Las primeras descartan opciones; las últimas desempatan:
- ¿Qué procesador tengo? Sin MMU y con pocos KB de RAM, Linux queda descartado. Con 8 KB de RAM, un RTOS con varias tareas es dudoso.
- ¿Cuántas actividades independientes hay? Una o dos: superloop. Cinco o más con ritmos distintos: planificador cooperativo o RTOS.
- ¿Cuál es el plazo más exigente y quién lo cumple? Para plazos de microsegundos, la ISR; para milisegundos con lógica no trivial, una tarea de alta prioridad.
- ¿Hay tareas largas? Una tarea que no se puede dividir y dura decenas de milisegundos pide desalojo (RTOS) o moverla a otro procesador.
- ¿Qué servicios necesito? Red completa, sistema de archivos, USB host o interfaz gráfica compleja suelen pedir RTOS con bibliotecas o Linux.
- ¿Cuánta energía tengo? Un dispositivo a pila que debe pasar la mayor parte del tiempo dormido se organiza por eventos, con superloop o RTOS «sin ticks»; Linux queda fuera.
- ¿Qué sabe el equipo y qué exige la normativa? La mejor arquitectura es la que el equipo puede mantener y, si hay certificación, la que ya tiene antecedentes certificados.
- ¿Cómo evoluciona el producto? Si va a crecer mucho, es más barato empezar con la estructura que lo sostendrá que migrar después.
Después de elegir, escribí la decisión con sus razones en un documento corto. Dentro de dos años, cuando alguien pregunte por qué no se usó un RTOS (o por qué sí), esa nota vale más que cualquier recuerdo.
12 · Comprensión
Confusiones frecuentes
«Un RTOS hace que el sistema sea más rápido»
No: agrega sobrecarga. Lo que hace es que el sistema sea predecible: garantiza que la tarea más importante se ejecute a tiempo aunque haya otras. Un superloop bien hecho puede ser más rápido en promedio y peor en el peor caso.
«Con interrupciones ya no necesito nada más»
Las interrupciones resuelven la urgencia, no la organización. Si la ISR crece y empieza a hacer trabajo pesado, bloquea todo lo demás y vuelve el problema. Y las variables compartidas con el bucle traen errores de concurrencia sutiles.
«Bare-metal es sinónimo de código desordenado»
Un programa sin sistema operativo puede estar muy bien organizado en capas y módulos. Lo que no tiene es un planificador externo: la disciplina para no bloquear la pone el programador.
«Linux embebido sirve para todo»
Es la opción más potente, pero también la más pesada: consume memoria y energía, tarda en arrancar y no garantiza plazos estrictos. Para una cerradura, un termostato o un sensor a pila, es el camino equivocado.
«Más tareas son más claridad»
Dividir en muchas tareas puede aclarar la lógica, pero cada una suma una pila, cambios de contexto y puntos de sincronización donde aparecen errores. Se separan las actividades que realmente son independientes, no cada función.
«Puedo cambiar de arquitectura cuando quiera»
Se puede, pero cuesta: la estructura del programa, el manejo de datos compartidos y las pruebas dependen de la arquitectura elegida. Conviene prever el crecimiento desde el principio.
13 · Práctica guiada
Predecí antes de comprobar
1. Elegir la arquitectura
Proponé una arquitectura para cada producto: (a) un control remoto de TV; (b) un controlador de motor que debe cerrar un lazo cada 100 µs y además comunicar por CAN; (c) una cámara IP con transmisión de video; (d) un sensor de humedad a pila que mide cada 10 minutos.
Ver solución
(a) Superloop (o por eventos con el procesador dormido): una función, plazos holgados. (b) Superloop con interrupciones o RTOS: el lazo de 100 µs va en una interrupción de temporizador y la comunicación en una tarea o en el bucle principal. (c) Linux embebido: video, red y archivos exigen un sistema completo. (d) Superloop por eventos con el procesador dormido casi todo el tiempo: es lo que minimiza el consumo.
2. Latencia de un superloop
En un superloop, una tarea tarda 40 ms y la atención de un evento, 1 ms. Un pulsador se consulta una vez por vuelta. ¿Cuál es la latencia máxima de respuesta? ¿Y cuál es la duración mínima que debe tener una pulsación para no perderse?
Ver solución
En el peor caso, el pulsador se presiona justo después de ser consultado y hay que esperar la vuelta completa: unos 40 ms más 1 ms de atención, es decir ≈ 41 ms. Para no perderse, la pulsación debe durar al menos lo que una vuelta, unos 40 ms. Una pulsación humana típica dura más de 50 ms, por eso con polling lento «casi siempre anda»... y falla de vez en cuando.
3. Probabilidad de ver un pulso
Una señal dura 5 ms y se consulta cada 20 ms, en instantes sin relación con la señal. ¿Qué fracción de los pulsos se detecta?
Ver solución
El pulso se detecta si la consulta cae dentro de sus 5 ms. Como las consultas están separadas 20 ms, la probabilidad es 5 / 20 = 25 %. Tres de cada cuatro pulsos se pierden. Es el mismo efecto que mostró el laboratorio (7 de 100 con una vuelta de 50 ms: 5 / 50,1 ≈ 10 %, del mismo orden que el 7 % observado).
4. Costo de memoria de un RTOS
Un RTOS ocupa 1,5 KB de RAM de núcleo y cada tarea necesita 512 bytes de pila. Con 3 tareas, ¿cuánta RAM se gasta? Si el chip tiene 8 KB, ¿qué porcentaje es?
Ver solución
1536 + 3 × 512 = 1536 + 1536 = 3072 bytes (3 KB). Sobre 8192 bytes es el 37,5 % de la RAM antes de escribir la primera variable de la aplicación. Con los márgenes del tema 2 (RAM hasta el 75 %), quedan solo unos 3 KB para el resto. Un RTOS en un chip con tan poca RAM es un compromiso apretado.
5. Sobrecarga del planificador
Un RTOS usa un tick de 1 ms y cada tick consume 10 µs de procesador entre atención de la interrupción y revisión del planificador. ¿Qué porcentaje del tiempo se gasta en esto? ¿Y con un tick de 100 µs?
Ver solución
Con 1 ms: 10 µs / 1000 µs = 1 %. Con un tick de 100 µs: 10 / 100 = 10 %. Subir la frecuencia del tick mejora la resolución temporal pero encarece el sistema, y también despierta más seguido al procesador, lo que importa en bajo consumo.
6. ¿Dentro o fuera de la ISR?
Decidí si cada acción debe hacerse dentro de una ISR de recepción de un puerto serie: (a) leer el byte recibido y guardarlo en un buffer; (b) armar un mensaje JSON con los datos; (c) limpiar el aviso de interrupción; (d) imprimir un texto con printf; (e) activar una bandera para el bucle.
Ver solución
Dentro de la ISR: (a), (c) y (e), que son rápidas y deterministas. Fuera de la ISR, en el bucle o en una tarea: (b) y (d), que son lentas, pueden bloquear y no son seguras para llamar desde una interrupción. La regla: la ISR toma el dato y avisa; otro lo procesa.
14 · Síntesis
Ideas para recordar
- Toda arquitectura de software de un firmware responde a una pregunta: quién decide qué se ejecuta y qué pasa cuando llegan varias cosas a la vez.
- Un firmware bien hecho se organiza en capas (aplicación, servicios, drivers, abstracción de hardware, hardware) para que el cambio de chip o de componente quede localizado.
- El superloop es la arquitectura más simple y ligera, pero la respuesta a un evento puede tardar una vuelta completa del bucle y los eventos cortos pueden perderse.
- Las interrupciones sacan lo urgente del bucle: el aviso es inmediato, pero si la atención se hace en el bucle sigue esperando; si se hace en la ISR, bloquea al resto.
- La planificación cooperativa y la programación por eventos ordenan el trabajo sin sistema operativo, a condición de que cada tarea sea corta y no bloquee.
- Un RTOS reparte el procesador entre tareas con prioridades y las desaloja cuando llega algo más importante: da predecibilidad y estructura, a cambio de memoria, sobrecarga y errores de concurrencia nuevos.
- Linux embebido ofrece un sistema completo (red, archivos, gráficos) sobre procesadores con MMU y mucha memoria, pero consume más, arranca lento y no garantiza plazos estrictos; muchos productos lo combinan con un microcontrolador de tiempo real.
- Se elige la arquitectura más simple que cumple los requisitos con margen, subiendo de nivel solo cuando hace falta y dejando por escrito las razones.
¿Listo para el tema 5?
Antes de avanzar, explicá con tus palabras por qué un superloop puede no ver un evento corto, qué diferencia hay entre la latencia de interrupción y el tiempo de respuesta, y qué arquitectura elegirías para un sensor a pila que mide una vez por minuto. Si podés justificar las tres respuestas, tenés el panorama de cómo se organiza un firmware.
En el próximo tema vemos el ciclo de desarrollo: cómo se convierte tu código en un binario para otro procesador (compilación cruzada), cómo se graba en el chip y cómo es el ciclo diario de editar, grabar y probar.