Rutinas de Interrupción (ISR) y GIC¶
El sistema LAMULA DRx responde en tiempo real a los eventos producidos por la Lógica Programable mediante el controlador de interrupciones del ARM Cortex-A9 (GIC pl390). Esta página detalla la configuración del GIC, el funcionamiento de la rutina de servicio de interrupción (ray_isr) y los flujos de secuencia extremo a extremo.
Interrupción del AXI DMA (IRQ 61 / IRQ_F2P[0])¶
El AXI DMA S2MM genera una interrupción de fin de transferencia cada vez que un rayo de radar se escribe completamente en la memoria RAM DDR3.
Diagrama del Flujo de Interrupción S2MM¶
sequenceDiagram
autonumber
participant PL_PACK as drx_ray_packer (PL)
participant PL_DMA as AXI DMA S2MM (PL)
participant GIC as ARM GIC pl390 (PS)
participant ISR as ray_isr() (Contexto ISR)
participant TSK as drx_ray (Tarea FreeRTOS)
PL_PACK->>PL_DMA: Emite último byte de rayo con TLAST = 1
PL_DMA->>PL_DMA: Escribe datos en DDR3 y actualiza descriptor
PL_DMA->>GIC: Aserta línea s2mm_introut (IRQ_F2P[0] - ID 61)
GIC->>ISR: Interrumpe CPU y salta a ray_isr()
ISR->>PL_DMA: XAxiDma_BdRingAckIrq() (Reconoce interrupción)
alt Error en DMA (XAXIDMA_IRQ_ERROR_MASK)
ISR->>ISR: Incrementa dma_errors y desactiva IRQ de error
else Transferencia Exitosa (XAXIDMA_IRQ_IOC_MASK)
ISR->>TSK: xSemaphoreGiveFromISR(g_sem, &woken)
ISR->>GIC: portYIELD_FROM_ISR(woken) (Solicita cambio contexto)
end
Note over TSK: Tarea drx_ray despierta e invoca reap()
Detalle del Código de la ISR (ray_isr en drx_ray.c)¶
La rutina de interrupción está optimizada para ejecutarse en la menor cantidad de ciclos de reloj posible:
/* fw/src/app/drx_ray.c */
static void ray_isr(void *ref)
{
(void)ref;
XAxiDma_BdRing *ring = XAxiDma_GetRxRing(g_dma);
u32 irq = XAxiDma_BdRingGetIrq(ring);
/* 1. Reconocer la interrupción en el controlador del DMA */
XAxiDma_BdRingAckIrq(ring, irq);
/* 2. Manejo de errores de hardware */
if ((irq & XAXIDMA_IRQ_ERROR_MASK) != 0u) {
g_status.dma_errors++;
/* Se desactiva la IRQ de error para evitar tormentas de interrupciones
* si la condición de error en el bus AXI persiste */
XAxiDma_BdRingIntDisable(ring, XAXIDMA_IRQ_ERROR_MASK);
}
/* 3. Manejo de fin de transferencia (Interrupt On Complete) */
if ((irq & (XAXIDMA_IRQ_IOC_MASK | XAXIDMA_IRQ_DELAY_MASK)) != 0u) {
BaseType_t woken = pdFALSE;
xSemaphoreGiveFromISR(g_sem, &woken);
portYIELD_FROM_ISR(woken);
}
}
Registro e Instalación de la ISR¶
Durante la llamada a DrxRay_Init(), la interrupción se registra en el vector de FreeRTOS/BSP mediante:
xPortInstallInterruptHandler(DRX_RAY_IRQ_ID, ray_isr, NULL);
vPortEnableInterrupt(DRX_RAY_IRQ_ID);
XAxiDma_BdRingIntEnable(ring, XAXIDMA_IRQ_ALL_MASK);
DRX_RAY_IRQ_ID equivale a la macro XPAR_FABRIC_DMA_S2MM_INTROUT_INTR (definida como 61 en xparameters.h).
Flujo Extremo a Extremo (Caso de Uso Principal)¶
El siguiente diagrama ilustra la trayectoria completa de una muestra desde la BRAM de estímulo en la PL hasta su transmisión por red hacia el procesador de señales DSP:
sequenceDiagram
autonumber
participant BRAM as vector_source (BRAM)
participant DDC as drx_ddc_quad_top
participant GATE as drx_range_gate_quad_top
participant PACK as drx_ray_packer
participant DMA as AXI DMA S2MM
participant DDR as Memoria RAM DDR3
participant ISR as ISR (ray_isr)
participant TSK_RAY as Tarea drx_ray
participant TSK_TX as Tarea drx_tx
participant DSP as LAMULA DSP (TCP)
BRAM->>DDC: Entrega muestras I/Q a tasa plena (62.5 MHz)
DDC->>GATE: Mezcla NCO + Decimación CIC + Filtro FIR
GATE->>PACK: Acumula celdas en BRAM ping-pong y emite rayo
PACK->>DMA: Agrega cabecera 0x52415931 + AXI4-Stream TLAST
DMA->>DDR: Transferencia Scatter-Gather AXI HP0 hacia DDR3
DMA->>ISR: Genera interrupción s2mm_introut (IRQ 61)
ISR->>TSK_RAY: Otorga semáforo binario g_sem
TSK_RAY->>DDR: Invalida caché CPU y lee cabecera/metadatos
TSK_RAY->>TSK_TX: Copia datos a slot y encola en g_listos
TSK_TX->>DSP: Transmite trama del contrato DRx↔DSP por TCP
Admoniciones sobre Manejo de Interrupciones¶
Cuidado con tormentas de interrupción en fallos AXI
Si ocurre un error en el bus AXI HP0 (por ejemplo, intento de acceso a una dirección no mapeada), el AXI DMA mantiene la línea de interrupción asertada. Reconocer la interrupción sin desactivar la máscara de error provocará reingresos infinitos a la ISR, congelando la CPU. Por esta razón, ray_isr() ejecuta XAxiDma_BdRingIntDisable(ring, XAXIDMA_IRQ_ERROR_MASK) si detecta un error.
Invalidador de caché en frontera DMA
Dado que la CPU lee los datos que el DMA acaba de escribir en DDR3, la invalidez de la caché debe aplicarse dos veces: en submit_buffer() antes de entregar el descriptor al DMA, y en deliver() inmediatamente antes de analizar la cabecera. Esto evita que el mecanismo de prefetch especulativo de la arquitectura ARM lea datos obsoletos.