# 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:
1. **IF (Instruction Fetch)** – Se lee la instrucción de memoria.
2. **ID (Instruction Decode)** – Se decodifica.
3. **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:
```C
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.
## 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:**
1. **Software:** el kernel revisa el uso de pila y lanza excepción si se supera.
2. **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).