Compartir vía


Administración de memoria y consideraciones sobre la latencia

Importante

Esta es la documentación de Azure Sphere (heredado). Azure Sphere (heredado) se retira el 27 de septiembre de 2027 y los usuarios deben migrar a Azure Sphere (integrado) en este momento. Use el selector de versiones situado encima de la TOC para ver la documentación de Azure Sphere (integrado).

En este tema se describen las consideraciones sobre la latencia y el uso de la memoria básico para las aplicaciones en tiempo real que se ejecutan en el chip MT3620.

Nota:

Para obtener más información sobre la configuración de memoria o DMA, consulte la hoja de datos de MT3620 publicada de MediaTek; si quedan preguntas, puede solicitar la hoja de datos "MT3620 M4" desde Avnet enviando un correo electrónico Azure.Sphere@avnet.coma .

Diseño de memoria en los núcleos en tiempo real

En la tabla siguiente se resume la memoria disponible en los núcleos en tiempo real:

Tipo de memoria Dirección base
TCM 0x00100000
Flash con XIP 0x10000000
SYSRAM 0x22000000

Cada núcleo en tiempo real tiene 192 KB de memoria directamente conectada (TCM) que se asigna en tres bancos de 64 KB, a partir de 0x00100000. Los acceso de la TCM son rápidos, pero solo el núcleo en tiempo real puede acceder a la memoria. La TCM no puede compartirse con una aplicación de alto nivel o con una aplicación con respuesta en tiempo real (RTApp) que se ejecuta en un núcleo diferente.

Cada núcleo en tiempo real también tiene 64 KB de SYSRAM, que se asigna a partir de 0x22000000. El controlador de DMA también puede dirigirse a SYSRAM, para que los periféricos puedan tener acceso a él. Los accesos a SYSRAM desde el núcleo en tiempo real son considerablemente más lentos que los accesos a TCM. Al igual que con TCM, SYSRAM no puede compartirse con otra aplicación.

La memoria flash de ejecución en contexto (XIP) se comparte con aplicaciones de alto nivel. Cada ventana de la asignación XIP de la memoria flash está visible para cada núcleo en la dirección 0x10000000. El sistema operativo configura la asignación de XIP antes de iniciar la aplicación, si el archivo de ELF de la aplicación contiene un segmento que tiene las siguientes propiedades:

  • La dirección de carga (como se especifica en la columna VirtAddr del encabezado del programa) es igual a 0x10000000.
  • El tamaño y el desplazamiento del archivo (como se especifica en los campos FileSiz y MemSiz del encabezado del programa) se adaptan al archivo de ELF de la aplicación.

Si hay un encabezado del programa con estas propiedades en el archivo de ELF de la aplicación, la ventana de XIP se colocará de tal modo que el segmento esté visible en 0x10000000. El archivo no puede tener más de un segmento XIP y debe apuntar a 0x10000000; no puede especificar ninguna otra dirección.

Implementación de ELF

Las imágenes de RTApp deben ser archivos de ELF. La imagen de ELF se encapsula en un paquete de imágenes de Azure Sphere y se implementa como una aplicación. Para cargar la aplicación, el sistema operativo de Azure Sphere inicia un cargador de ELF que se ejecuta en el núcleo en tiempo real. El cargador procesa cada segmento LOAD en el archivo de ELF y lo carga en el tipo de memoria indicado por la dirección virtual en el encabezado del programa.

Use arm-none-eabi-readelf.exe -l (con L minúscula), que forma parte de la cadena de herramientas GNU Arm Embedded Toolchain, para mostrar los encabezados del programa de la aplicación. La columna de dirección virtual (VirtAddr) que aparece en el encabezado indica la dirección de destino para el segmento de carga. No significa que el propio procesador realice alguna traducción adicional. El cargador de ELF de Azure Sphere no usa la dirección física (PhysAddr).

Considere este ejemplo:

Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  LOAD           0x000098 0x00100000 0x00100000 0x00000 0x00e78 RW  0x8
  LOAD           0x0000a0 0x10000000 0x10000000 0x03078 0x03078 RWE 0x10
  LOAD           0x003118 0x00100e78 0x10003078 0x000f0 0x000f0 RW  0x4
  • El segmento de 0x00100000 está destinado a la memoria directamente conectada (TCM). El cargador copia los datos desde el paquete de imágenes en la RAM o inicializa en cero la TCM, según sea necesario.

  • El segmento de 0x10000000 se asigna a la ventana de XIP para el núcleo. En tiempo de ejecución, los accesos a 0x10000000 + offset se traducen en <address-of-XIP-segment-in-flash> + offset cuando abandonan el núcleo en tiempo real.

  • El segmento de datos de la dirección virtual 0x00100e78 se asigna a TCM.

Consideraciones sobre ELF en tiempo de ejecución

El cargador de ELF realiza algunas de las tareas que realizaría un binario sin formato o el cargador de arranque encadenado durante el inicio. En concreto, inicializa en cero los datos de bloques iniciados por símbolos (BSS) y copia los datos inicializados, pero mutables, de la memoria flash de solo lectura a la RAM, según los encabezados del programa. Después, la aplicación los inicia y ejecuta sus propias funciones de inicialización. En la mayoría de los casos, los cambios realizados en las aplicaciones existentes no se requieren. Llenar con ceros los datos de BSS en la aplicación resulta innecesario pero inofensivo, porque el cargador ya ha llenado la memoria de ceros.

La copia de datos mutables de flash a RAM puede dar lugar a problemas en algunas circunstancias, dependiendo de cómo se disponga el archivo ELF. El cargador ELF procesa los encabezados del programa secuencialmente, sin cambiar el diseño general de los segmentos del archivo. Después, asigna no solo el propio segmento de XIP a 0x10000000, sino también todos los segmentos posteriores en orden. Si los segmentos del archivo de ELF presentan un orden secuencial sin ningún espacio ni alineación, el código de inicio del sistema operativo puede usar la aritmética de puntero para buscar el inicio del segmento de datos. Sin embargo, si el archivo de ELF tiene un diseño distinto, la aritmética de puntero no genera la dirección correcta como resultado, por lo que el código de inicio de la aplicación no debe intentar copiar la sección de datos. Esto puede ocasionar problemas si la aplicación o los objetivos de tiempo de recuperación usan un cargador de inicio encadenado o necesitan el lanzamiento controlado de una pila antes de llenar BSS con ceros o de inicializar los datos mutables.

Destinos de memoria

Para establecer el destino del código en la TCM, la memoria flash con XIP o SYSRAM, edite el script linker.ld para la aplicación. Las aplicaciones de ejemplo de Azure Sphere se ejecutan desde TCM, pero el archivo de script linker.ld para cada aplicación describe cómo usar la memoria flash con XIP como destino en su lugar. Tal y como se muestra en el ejemplo siguiente, puede cambiar un ejemplo para ejecutarlo en XIP con el alias CODE_REGION y RODATA_REGION en FLASH en lugar de la TCM predeterminada:

REGION_ALIAS("CODE_REGION", FLASH);
REGION_ALIAS("RODATA_REGION", FLASH);

Para determinar si una aplicación compilada se ejecuta desde TCM o la memoria flash con XIP, use arm-none-eabi-readelf.exe, que forma parte de la cadena de herramientas GNU Arm Embedded Toolchain. Ejecútela en el archivo .out, que está en el mismo directorio que el paquete de imagen, y especifique la marca -l (L minúscula) para ver dónde se han guardado el código y los datos de solo lectura. El código y los datos de solo lectura almacenados en la memoria flash se cargan en la dirección 0x10000000; en cambio, el código y los datos almacenados en la TCM se cargan en 0x00100000.

En el ejemplo siguiente se muestra una aplicación que se ejecuta desde la memoria flash.

arm-none-eabi-readelf.exe -l UART_RTApp_MT3620_BareMetal.out

Elf file type is EXEC (Executable file)
Entry point 0x10000000
There are 2 program headers, starting at offset 52

Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  LOAD           0x000074 0x00100000 0x00100000 0x00284 0x003c0 RW  0x4
  LOAD           0x000300 0x10000000 0x10000000 0x013b9 0x013b9 R E 0x10

 Section to Segment mapping:
  Segment Sections...
   00     .data .bss
   01     .text .rodata

Ubicación de la tabla de vectores

En los dispositivos ARMv7-M, la tabla de vectores debe estar alineada con un límite a la potencia de dos que tenga al menos 128 bytes y un tamaño como mínimo similar al de la tabla, como se indica en el Manual de referencia de arquitectura de ARMv7-M. Cada núcleo RT de E/S en mt3620 admite 100 interrupciones externas. Por lo tanto, incluyendo el puntero de la pila y 15 excepciones estándar, la tabla tiene 116 entradas de 4 bytes, con un tamaño total de 464 bytes, que se redondea hasta 512 bytes.

Cuando el código se ejecuta desde flash con XIP, la tabla de vectores debe colocarse en 0x10000000 y alinearse con un límite de 32 bytes en el archivo ELF. Cuando el código no se ejecuta desde flash con XIP, la tabla suele colocarse al principio de TCM0, que es 0x100000. En cualquier caso, para asegurarse de que la dirección virtual de la tabla está correctamente alineada, coloque la tabla de vectores en una sección dedicada y establezca CODE_REGION en la dirección adecuada.

Los ejemplos de MT3620 BareMetal del repositorio de ejemplos de Azure Sphere muestran cómo hacer esto. La declaración de la tabla de vectores en main.c establece su atributo section en .vector_table. El script del enlazador agrega el alias CODE_REGION al principio de TCM o XIP y el atributo ALIGN establece la alineación de la sección de texto dentro del archivo ELF de la siguiente manera:

SECTIONS
{
    .text : ALIGN(32) {
        KEEP(*(.vector_table))
        *(.text)
    } >CODE_REGION
...
}

Consideraciones sobre la latencia y en tiempo real

Las RTApps y las aplicaciones de alto nivel compiten por acceder a la memoria flash, aunque no se comuniquen entre sí. Como resultado, las RTApps que se ejecutan desde la memoria flash con XIP pueden encontrar una latencia alta e imprevisible. Las escrituras en la memoria flash, como durante una actualización, pueden implicar picos de latencia de hasta varios cientos de milisegundos. En función de los requisitos de su aplicación, puede administrar esta situación de varias formas:

  • Coloque todo el código y los datos en la TCM. El código que se ejecuta desde la TCM no es vulnerable a la contención para la memoria flash.

  • Divida el código en secciones críticas y no críticas y ejecute el código no crítico desde la memoria flash. El código que tiene requisitos en tiempo real, como un temporizador guardián, no debería tener que ejecutarse cuando otro código accede a la memoria flash. En Memory targets (Destinos de memoria) se describe cómo tener como destino la memoria flash con XIP en lugar de la TCM.

  • Utilice la memoria caché. Una aplicación puede usar el lote más bajo de 32 KB de la TCM como la caché con XIP. Este enfoque no ofrece garantías sólidas en tiempo real en caso de que se produzca un error de la caché, pero mejora el rendimiento normal sin necesidad de requerir que se mueva todo el código a la RAM. Consulte la hoja de datos "MT3620 M4" para obtener información sobre la configuración de caché XIP.