Files
etsii-vault/CUARTO/SETR2/Teoria_2526.md
2025-10-09 19:25:27 +02:00

227 lines
16 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# <mark style="background: #FFF3A3A6;">TEMA 1: Introducción a ARM</mark>
## <mark style="background: #ADCCFFA6;">1. Introducción</mark>
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).
## <mark style="background: #ADCCFFA6;">2. Estructura general del Cortex-M4 y sus registros</mark>
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.
### <mark style="background: #FFB86CA6;">Registros generales</mark>
- **R0R12** → 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.
### <mark style="background: #FFB86CA6;">Registros de estado</mark>
- **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.
### <mark style="background: #FFB86CA6;">Registros de coma flotante</mark>
- 32 registros de 32 bits (**S0S31**) → precisión simple.
- 16 registros de 64 bits (**D0D15**) → 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.
## <mark style="background: #ADCCFFA6;">3. Ejecución de instrucciones: Pipeline, modos Thumb y eficiencia</mark>
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).
### <mark style="background: #FFB86CA6;">Instrucciones Thumb y Thumb-2</mark>
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.
## <mark style="background: #ADCCFFA6;">4. Memoria y organización interna</mark>
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.
### <mark style="background: #FFB86CA6;">Bit-band Mapping</mark>
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.
### <mark style="background: #FFB86CA6;">Jerarquía de buses en STM32F4</mark>
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.
## <mark style="background: #ADCCFFA6;">5. Interrupciones, excepciones y control del sistema</mark>
El Cortex-M4 incluye varios módulos clave para gestionar eventos externos o internos:
### <mark style="background: #FFB86CA6;">NVIC (Nested Vector Interrupt Controller)</mark>
- 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.
### <mark style="background: #FFB86CA6;">SCB (System Control Block)</mark>
Contiene info del sistema, versión del core, vector de interrupciones, etc.
### <mark style="background: #FFB86CA6;">MPU (Memory Protection Unit)</mark>
Define zonas de memoria con permisos específicos, previniendo accesos indebidos (muy útil con RTOS).
### <mark style="background: #FFB86CA6;">SysTick</mark>
Temporizador de 24 bits que genera interrupciones periódicas.
En RTOS se usa como *tick del sistema* para planificar tareas.
### <mark style="background: #FFB86CA6;">Tipos de excepciones más comunes</mark>
- **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.
## <mark style="background: #ADCCFFA6;">6. STM32F407: el ejemplo clásico del Cortex-M4</mark>
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**:
### <mark style="background: #FFB86CA6;"> ART Accelerator</mark>
- 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**.
## <mark style="background: #ADCCFFA6;">7. Arranque, reloj y desarrollo</mark>
### <mark style="background: #FFB86CA6;">Modos de arranque (BOOT0 y BOOT1)</mark>
- **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.
### <mark style="background: #FFB86CA6;">Sistema de relojes</mark>
- **HSI (16 MHz interno)** y **HSE (426 MHz externo)**.
- **PLL** multiplica frecuencia hasta 168 MHz (para core y buses).
- Algunos periféricos (USB, SDIO, I2S) necesitan la precisión del HSE.
### <mark style="background: #FFB86CA6;">Entorno de desarrollo</mark>
- **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.
## <mark style="background: #ADCCFFA6;">8. Ecosistema STM32 y placas de desarrollo</mark>
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.
# <mark style="background: #FFF3A3A6;">Tema 2 Sistemas en Tiempo Real</mark>
## <mark style="background: #ADCCFFA6;">1. Qué es un Sistema en Tiempo Real (STR)</mark>
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).
### <mark style="background: #FFB86CA6;">Tipos de sistemas en tiempo real</mark>
- **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).
## <mark style="background: #ADCCFFA6;">2. Modelos de programación</mark>
### <mark style="background: #FFB86CA6;">Procesamiento secuencial (bucle de scan)</mark>
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.
### <mark style="background: #FFB86CA6;">Primer plano / segundo plano (Foreground / Background)</mark>
- 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.
### <mark style="background: #FFB86CA6;">Multitarea</mark>
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.
## <mark style="background: #ADCCFFA6;">3. Cuándo usar un RTOS</mark>
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.**
### <mark style="background: #FFB86CA6;">Ventajas del RTOS</mark>
- **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.
## <mark style="background: #ADCCFFA6;">4. Núcleo y planificación de tareas</mark>
### <mark style="background: #FFB86CA6;">El planificador</mark>
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).
### <mark style="background: #FFB86CA6;">Políticas de planificación</mark>
- **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.
## <mark style="background: #ADCCFFA6;">5. Tareas en un RTOS</mark>
### <mark style="background: #FFB86CA6;">Concepto general</mark>
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).
### <mark style="background: #FFB86CA6;">Tipos de tareas</mark>
- **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.
## <mark style="background: #ADCCFFA6;">6. Control de tareas y memoria</mark>
### <mark style="background: #FFB86CA6;">Estados de una tarea</mark>
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.
### <mark style="background: #FFB86CA6;">Bloques de Control de Tareas (TCB)</mark>
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).
### <mark style="background: #FFB86CA6;">Memoria y pila</mark>
- 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.
## <mark style="background: #ADCCFFA6;">7. Hooks del RTOS y gestión de errores</mark>
### <mark style="background: #FFB86CA6;">Hooks</mark>
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.
## <mark style="background: #ADCCFFA6;">8. Timers Software</mark>
### <mark style="background: #FFB86CA6;">Qué son</mark>
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.
### <mark style="background: #FFB86CA6;">Gestión interna</mark>
- 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).