16 KiB
TEMA 1: Introducción a ARM
1. Introducción
ARM (Advanced RISC Machines) nació en 1990 en Inglaterra con una idea clara: procesadores RISC, simples y eficientes, frente a los CISC de Intel y compañía.
No fabrican chips, venden licencias de sus diseños, así que empresas como ST, NXP, Texas Instruments o Microchip integran sus núcleos en sus propios micros.
Las arquitecturas ARM se dividen en:
- Cortex-A: para sistemas potentes (Android, Linux, etc.).
- Cortex-R: para sistemas de tiempo real críticos (automoción, industria).
- Cortex-M: para microcontroladores de bajo consumo y control embebido (como los STM32).
El Cortex-M4 es un modelo intermedio: más potente que el M0/M3, pero más eficiente que el M7. Tiene soporte para operaciones en coma flotante y un rendimiento excelente en control digital y procesamiento de señales (DSP).
2. Estructura general del Cortex-M4 y sus registros
El núcleo Cortex-M4 es de 32 bits, arquitectura RISC, y usa una versión reducida del conjunto de instrucciones ARM llamada Thumb-2, que combina instrucciones de 16 y 32 bits para optimizar memoria sin perder rendimiento.
Registros generales
- R0–R12 → registros de propósito general (datos, direcciones, etc.).
- R13 (SP) → Stack Pointer, apunta a la cima de la pila.
- R14 (LR) → Link Register, guarda la dirección de retorno tras una llamada a subrutina.
- R15 (PC) → Program Counter, indica la instrucción actual.
Registros de estado
- PSR (Program Status Register) → conjunto de tres registros (APSR, IPSR, EPSR) que indican el estado del procesador, la instrucción en ejecución y las interrupciones activas.
- CONTROL → define el nivel de privilegio, la pila activa y si la FPU está disponible.
Registros de coma flotante
- 32 registros de 32 bits (S0–S31) → precisión simple.
- 16 registros de 64 bits (D0–D15) → precisión doble (empaquetados en los S).
- FPSCR → contiene flags como negativo, cero, overflow, NaN o modo de redondeo. Este diseño permite al Cortex-M4 realizar cálculos complejos en tiempo real sin depender de software lento, ideal para audio, sensores o controladores PID.
3. Ejecución de instrucciones: Pipeline, modos Thumb y eficiencia
El pipeline (tubería de ejecución) del Cortex-M4 tiene 3 etapas:
- IF (Instruction Fetch) – Se lee la instrucción de memoria.
- ID (Instruction Decode) – Se decodifica.
- EX (Execute) – Se ejecuta. Esto permite solapar instrucciones, mejorando el rendimiento (una instrucción por ciclo en el mejor caso).
Instrucciones Thumb y Thumb-2
ARM clásico usa instrucciones de 32 bits (rápidas, pero grandes).
Thumb (16 bits) mejora la densidad de código (programas más pequeños), aunque algo más lentos (~20% más).
Thumb-2 mezcla ambas: usa 16 bits para instrucciones simples y 32 bits para las complejas. Así:
- Se ahorra ≈30% de memoria.
- Se mantiene rendimiento casi igual al modo ARM. En sistemas embebidos donde la memoria Flash es limitada, esta diferencia es clave.
4. Memoria y organización interna
Los ARM Cortex-M trabajan con una organización de memoria alineada a 32 bits, aunque el M4 admite accesos desalineados, lo que mejora el aprovechamiento de la RAM.
Bit-band Mapping
Permite acceder a bits individuales de una palabra mediante direcciones alias.
Por ejemplo: escribir directamente el bit 0 de un registro sin usar máscaras.
Esto facilita muchísimo el control de GPIO o flags sin operaciones lógicas extra.
Jerarquía de buses en STM32F4
Dentro del micro, los distintos módulos (CPU, DMA, periféricos, memorias) se conectan por una red de buses:
- AHB1/AHB2 (168 MHz): periféricos rápidos (GPIO, USB FS, DMA).
- APB2 (84 MHz): periféricos intermedios (ADC, timers).
- APB1 (42 MHz): periféricos lentos (USART, I2C).
Esto evita cuellos de botella y permite que la CPU y el DMA trabajen en paralelo.
5. Interrupciones, excepciones y control del sistema
El Cortex-M4 incluye varios módulos clave para gestionar eventos externos o internos:
NVIC (Nested Vector Interrupt Controller)
- Permite interrupciones anidadas con diferentes niveles de prioridad (hasta 150 líneas).
- Las más prioritarias pueden interrumpir a otras de menor prioridad.
- Soporta cambio rápido de contexto (“tail-chaining”) y evita restauraciones innecesarias.
- También gestiona Late-Arrival, cuando llega una interrupción urgente en medio del cambio de contexto.
SCB (System Control Block)
Contiene info del sistema, versión del core, vector de interrupciones, etc.
MPU (Memory Protection Unit)
Define zonas de memoria con permisos específicos, previniendo accesos indebidos (muy útil con RTOS).
SysTick
Temporizador de 24 bits que genera interrupciones periódicas.
En RTOS se usa como tick del sistema para planificar tareas.
Tipos de excepciones más comunes
- Reset: reinicia el procesador.
- HardFault: error grave (por ejemplo, ISR no definida).
- MemManage / BusFault / UsageFault: fallos de acceso o ejecución. También hay interrupciones software, disparadas desde código:
- SVCall: llamada a supervisor (modo privilegiado).
- PendSV: cambio de contexto entre tareas (RTOS).
- SysTick: temporizador base del sistema operativo.
6. STM32F407: el ejemplo clásico del Cortex-M4
El STM32F407 de STMicroelectronics es el ejemplo típico para este núcleo:
- Frecuencia máxima: 168 MHz (≈210 DMIPS).
- 1 MB Flash / 192 KB SRAM.
- 3 ADC de 12 bits, 2 DAC, 17 timers, 2 DMA.
- Interfaces: USB OTG, CAN, SPI, I²C, USART, SDIO, Ethernet, cámara digital.
- FSMC: permite usar memorias externas (Flash, SRAM).
La memoria Flash es relativamente lenta (4 ciclos de lectura por palabra), pero ST lo soluciona con el ART Accelerator:
ART Accelerator
- Usa una prefetch queue para precargar bloques de instrucciones.
- Tiene predictor de saltos y branch cache, reduciendo esperas.
- Si la predicción acierta, el procesador no pierde ciclos y mantiene CPI ≈ 1.
7. Arranque, reloj y desarrollo
Modos de arranque (BOOT0 y BOOT1)
- Modo 0: arranca desde la Flash (modo normal).
- Modo 1: arranca desde el Bootloader interno (permite reprogramar por USB, UART, etc.).
- Modo 3: arranque desde memoria externa.
El Bootloader es esencial para recuperar un micro "brickeado" o actualizar firmware sin programador.
Sistema de relojes
- HSI (16 MHz interno) y HSE (4–26 MHz externo).
- PLL multiplica frecuencia hasta 168 MHz (para core y buses).
- Algunos periféricos (USB, SDIO, I2S) necesitan la precisión del HSE.
Entorno de desarrollo
- Keil MDK-ARM: compilador comercial, muy optimizado (pago).
- STM32CubeIDE: gratuito, basado en Eclipse + GCC, integra configuración, generación de código y depuración.
- MEMS Studio / X-CUBE-AI / NanoEdge AI: herramientas de ST para sensores, IA y análisis de datos.
8. Ecosistema STM32 y placas de desarrollo
ST ofrece un entorno completo para prototipar y desarrollar:
- Placas Discovery (como STM32F4-Discovery): traen periféricos, LEDs y sensores.
- Nucleo Boards: diferentes tamaños (32, 64, 144 pines), con compatibilidad Arduino.
- DISCO-L475VG-IOT01A: ideal para proyectos IoT, con sensores, WiFi y BLE.
- Nuevos modelos como STM32MP157 (dual-core con Linux) y STM32N6 para IA y edge computing.
Tema 2 – Sistemas en Tiempo Real
1. Qué es un Sistema en Tiempo Real (STR)
Un sistema en tiempo real (RTS, Real-Time System) es aquel en el que la validez del resultado depende no solo de que sea correcto, sino de que se obtenga dentro de un plazo concreto (deadline). No basta con que funcione, debe hacerlo a tiempo.
En sistemas de propósito general lo importante es la exactitud del resultado, mientras que en tiempo real lo crucial es cumplir los plazos de respuesta, buscando comportamiento determinista más que potencia bruta.
(Ejemplo: un STM32 a 168 MHz puede ser más fiable que un i9 a 4.5 GHz si debe garantizar tiempos exactos).
Tipos de sistemas en tiempo real
- Tiempo real duro: el incumplimiento del plazo provoca fallo catastrófico (ej: marcapasos).
- Tiempo real firme: el retraso degrada el sistema, pero no lo destruye (ej: router).
- Tiempo real blando: el retraso resta utilidad, pero el resultado sigue siendo válido (ej: termómetro).
2. Modelos de programación
Procesamiento secuencial (bucle de scan)
Estructura básica:
while(1)
{
Task1();
Task2();
...
TaskN();
}
- Todas las tareas se ejecutan una tras otra.
- No se permiten esperas bloqueantes ni interrupciones largas.
- El periodo total del sistema equivale a la duración del bucle.
- Comunicación entre tareas mediante variables globales.
- Tiene variabilidad temporal, ya que no todas las tareas tardan lo mismo.
Primer plano / segundo plano (Foreground / Background)
- Es un superloop con interrupciones.
- Problemas comunes:
- Accesos simultáneos a variables globales (condiciones de carrera).
- Evitar esperas bloqueantes dentro del bucle.
- Aparece el fenómeno de Loop Jitter: el tiempo del ciclo varía según interrupciones, caché o condiciones de código.
Multitarea
Uso de múltiples tareas concurrentes coordinadas por un RTOS (Real-Time Operating System).
Cada tarea puede bloquearse esperando eventos, y el planificador decide cuál se ejecuta en cada instante.
3. Cuándo usar un RTOS
Un RTOS se emplea cuando la aplicación requiere:
- Determinismo: misma respuesta ante el mismo estímulo.
- Fiabilidad: detección y recuperación de errores.
- Complejidad: demasiadas funciones para un simple superloop.
- Operación fail-soft: capacidad de degradarse sin colapsar.
- Múltiples tareas concurrentes o temporizadas.
Ventajas del RTOS
- Modularidad: código dividido en tareas independientes.
- Mantenibilidad y extensibilidad: fácil de modificar o ampliar.
- Reusabilidad y portabilidad: las tareas pueden migrar entre plataformas.
- Trabajo en equipo: distintos devs trabajan en tareas separadas.
- Facilidad de testeo: permite probar tareas por separado.
- Eficiencia energética: evita esperas activas y permite modos de bajo consumo.
4. Núcleo y planificación de tareas
El planificador
El planificador es el núcleo del RTOS y decide qué tarea se ejecuta en cada momento.
Se ejecuta:
- Periódicamente (por interrupción SysTick).
- Cuando una tarea se bloquea o libera un recurso.
Debe ser rápido, determinista y eficiente (normalmente implementado en ensamblador).
Políticas de planificación
- Dinámicas: cambian prioridades en tiempo de ejecución (ej: EDF – Earliest Deadline First).
- Alta precisión pero poca estabilidad en sobrecarga.
- Estáticas: prioridades fijas asignadas al compilar.
- Colaborativas: la tarea decide cuándo ceder la CPU (yield).
- Simples pero poco fiables; una tarea puede bloquear todo.
- Apropiativas: la CPU pasa automáticamente a la tarea de mayor prioridad lista.
- Determinismo alto, ideal para sistemas embebidos.
- Colaborativas: la tarea decide cuándo ceder la CPU (yield).
5. Tareas en un RTOS
Concepto general
Una tarea es un bucle infinito que ejecuta su código y luego se bloquea esperando un evento.
El planificador ejecuta siempre la tarea lista con mayor prioridad.
Si varias tienen la misma prioridad → round-robin (rotación en cada tick).
Bloqueos posibles:
- Semáforos, colas, notificaciones.
- Esperas temporales (por ticks o tiempo real).
Tipos de tareas
- Cíclicas: se repiten indefinidamente.
- Periódicas: ejecutadas con una frecuencia fija.
- Eventuales: activadas por eventos externos.
- One-Shot: se crean, ejecutan una vez y se destruyen.
6. Control de tareas y memoria
Estados de una tarea
Estados principales:
- Ready: lista para ejecutarse.
- Running: ejecutándose.
- Blocked: esperando evento o tiempo.
- Suspended/Deleted: detenida o eliminada.
El planificador mueve las tareas entre estos estados según su situación.
Bloques de Control de Tareas (TCB)
Cada tarea tiene un TCB (Task Control Block) con:
- Puntero a pila y código.
- Prioridad y estado.
- Datos de uso de CPU/pila.
- Enlaces a otras tareas (listas enlazadas).
Memoria y pila
- Cada tarea tiene su propia pila, donde se guarda su contexto (variables locales, direcciones de retorno, registros).
- Las variables globales se almacenan en una memoria común. Detección de desbordes:
- Software: el kernel revisa el uso de pila y lanza excepción si se supera.
- Hardware: MPU/MMU detecta accesos fuera de rango y genera una excepción.
7. Hooks del RTOS y gestión de errores
Hooks
Tareas internas del RTOS que reaccionan a eventos especiales:
- Idle Task: se ejecuta cuando no hay ninguna tarea lista; no puede bloquearse.
- Stack Overflow Hook: se lanza al detectar desbordamiento de pila.
Suspende la tarea afectada y permite ejecutar acciones como reset, aviso o modo seguro.
8. Timers Software
Qué son
Un timer software es una función que se ejecuta con una periodicidad fija.
No pueden usar llamadas bloqueantes del RTOS.
Tipos:
- One-Shot: se ejecuta una sola vez tras un tiempo (ej: WatchDog).
- Periódico: se repite cada cierto periodo.
Gestión interna
- Controlados por la tarea interna TimerServiceTask.
- No usan timers hardware, sino el tick del sistema.
- Cada timer se gestiona con una cola de mensajes interna.
- Los callbacks usan la pila de TimerServiceTask (configurable).