Considerazioni sulla gestione della memoria e della latenza

Questo argomento descrive le considerazioni di base sull'uso della memoria e sulla latenza per le applicazioni in tempo reale eseguite sul chip MT3620.

Nota

Per ulteriori dettagli sulla configurazione della memoria o DMA, vedi il foglio dati MT3620 pubblicato da MediaTek; se restano domande, puoi richiedere "MT3620 M4 Datasheet" a Avnet inviando un messaggio e-mail Azure.Sphere@avnet.com.

Layout della memoria sui core in tempo reale

La tabella seguente riepiloga la memoria disponibile nei core in tempo reale:

Tipo di memoria Indirizzo di base
TCM 0x00100000
Flash XIP 0x10000000
SYSRAM 0x22000000

Ogni core in tempo reale ha 192 KB di memoria strettamente accoppiata (TCM), che viene mappata in tre banche di 64 KB a partire da 0x00100000. Gli accessi TCM sono veloci, ma solo il core in tempo reale può accedere alla memoria. TCM non può essere condiviso con un'applicazione di alto livello o con un'applicazione che supporta il tempo reale (RTApp) che viene eseguita su un altro core.

Ogni core in tempo reale ha anche 64 KB di SYSRAM, mappato a partire da 0x22000000. Il controller DMA può anche mirare SYSRAM, in modo che le periferiche possano accedervi. Gli accessi a SYSRAM dal core in tempo reale sono più lenti rispetto agli accessi a TCM. Come con TCM, SYSRAM non può essere condiviso con un'altra applicazione.

La memoria flash execute-in-place (XIP) viene condivisa con applicazioni di alto livello. Una finestra nel mapping XIP del flash è visibile a ogni core all'indirizzo 0x10000000. Il sistema operativo configura il mapping XIP prima di avviare l'applicazione se il file ELF dell'applicazione contiene un segmento con le proprietà seguenti:

  • L'indirizzo di caricamento ,come specificato nella colonna VirtAddr dell'intestazione programma, è uguale a 0x10000000
  • L'offset e le dimensioni del file (come specificato nei campi FileSiz e MemSiz nell'intestazione programma) rientrano nel file ELF dell'applicazione

Se un'intestazione di programma con queste proprietà è presente nel file ELF dell'applicazione, la finestra XIP sarà posizionata in modo che il segmento sia visibile in 0x10000000. Il file non può avere più di un segmento XIP e deve puntare a 0x10000000; non può specificare altri indirizzi.

Distribuzione ELF

Le immagini RTApp devono essere file ELF. L'immagine ELF viene avvolta in un pacchetto di immagini Azure Sphere e distribuita come applicazione. Per caricare l'applicazione, il sistema operativo Azure Sphere avvia un caricatore ELF che viene eseguito sul core in tempo reale. Il caricatore elabora ogni segmento LOAD nel file ELF e lo carica nel tipo di memoria indicato dall'indirizzo virtuale nell'intestazione del programma.

Utilizzare arm-none-eabi-readelf.exe -l (L in minuscolo), che fa parte del toolchain EMBEDDED ARM, per visualizzare le intestazioni del programma per l'applicazione. La colonna indirizzo virtuale (VirtAddr) visualizzata nell'intestazione indica l'indirizzo di destinazione per il segmento di caricamento. Ciò non significa che il processore stesso esegue qualsiasi traduzione aggiuntiva. Il caricatore Azure Sphere ELF non usa l'indirizzo fisico (PhysAddr).

Si consideri questo esempio:

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
  • Il segmento a 0x00100000 è puntato a una memoria strettamente associata (TCM). Il caricatore copia i dati dal pacchetto di immagini nella RAM o inizializza zero il TCM in base alle esigenze.

  • Il segmento in 0x10000000 viene mappato alla finestra XIP per il core. In fase di esecuzione, gli accessi vengono 0x10000000 + offset tradotti in <address-of-XIP-segment-in-flash> + offset quando lasciano il core in tempo reale.

  • Il segmento di dati all'indirizzo virtuale 0x00100e78 è mappato a TCM.

Considerazioni sul runtime ELF

Il caricatore ELF esegue alcune delle attività che un bootloader non elaborato binario (o concatenato) avrebbe eseguito all'avvio. In particolare, zero-inizializza i dati di tipo block-started-by-symbol (BSS) e copia i dati inizializzati ma mutable da flash di sola lettura nella RAM, in base alle intestazioni del programma. L'applicazione viene quindi avviata ed esegue le proprie funzioni di inizializzazione. Nella maggior parte dei casi, le modifiche alle applicazioni esistenti non sono necessarie. L'azzeramento dei dati BSS nell'applicazione è inutile ma innocuo, perché il caricatore ha già azzerato la memoria.

La copia di dati modificabili da flash a RAM può in alcuni casi causare problemi, a seconda di come è disposto il file ELF. Il caricatore ELF elabora le intestazioni del programma in sequenza, senza modificare il layout complessivo dei segmenti nel file. Mappa quindi non solo il segmento XIP stesso a 0x10000000, ma anche eventuali segmenti successivi in ordine. Se i segmenti nel file ELF sono in ordine sequenziale senza allineamento o vuoti, il codice di avvio del sistema operativo può utilizzare aritmetici puntatore per trovare l'inizio del segmento di dati. Se il file ELF ha un layout diverso, tuttavia, aritmetica puntatore non si tradurrà nell'indirizzo corretto, in modo che il codice di avvio dell'applicazione non deve tentare di copiare la sezione dati. Questo può causare problemi se l'applicazione o RTOS utilizza un bootloader concatenato o deve configurare uno stack canary prima di azzerare BSS o inizializzare i dati modificabili.

Target di memoria

È possibile assegnare codice su TCM, XIP flash o SYSRAM modificando lo script linker.ld per l'applicazione. Le applicazioni di esempio Azure Sphere vengono eseguite da TCM, ma il file di script linker.ld per ogni applicazione descrive come usare la flash XIP come destinazione. Come illustrato nell'esempio seguente, è possibile modificare un esempio da eseguire su XIP aliasando CODE_REGION e RODATA_REGION in FLASH anziché nel TCM predefinito:

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

Per determinare se un'applicazione compilata viene eseguita da flash TCM o XIP, utilizzare arm-none-eabi-readelf.exe, che fa parte del toolchain EMBEDDED di XIX. Eseguirlo sul file .out, che si trova nella stessa directory del pacchetto di immagini, e specificare il -l flag (L in minuscolo) per vedere dove sono stati inseriti il codice e i dati di sola lettura. Il codice e i dati di sola lettura che sono in memoria flash vengono caricati all'indirizzo 0x10000000; codice e dati in TCM vengono caricati nell'area TCM.

L'esempio seguente mostra un'applicazione che viene eseguita dalla 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

Posizione della tabella vettoriale

Nei dispositivi ARMv7-M, la tabella vettoriale deve essere allineata su un limite di potenza di due che è di almeno 128 byte e non inferiore alle dimensioni della tabella, come indicato nel manuale di riferimento per l'architettura ARMv7-M. Ogni core I/O RT sull'MT3620 supporta 100 interrupt esterni. Di conseguenza, includendo il puntatore dello stack e 15 eccezioni standard, la tabella ha 116 voci a 4 byte, per una dimensione totale di 464 byte, che arrotonda per eccesso a 512 byte.

Quando il codice viene eseguito da flash XIP, la tabella vettoriale deve essere posizionata in corrispondenza di 0x10000000 e deve essere allineata su un limite di 32 byte all'interno del file ELF. Quando il codice non viene eseguito da XIP flash, la tabella viene in genere posizionata all'inizio di TCM0, che è 0x100000. In entrambi i casi, per assicurarsi che l'indirizzo virtuale della tabella sia allineato correttamente, inserire la tabella vettoriale in una sezione dedicata e impostare CODE_REGION sull'indirizzo appropriato.

I campioni BareMetal MT3620 nel repository Azure Sphere Samples mostrano come farlo. La dichiarazione della tabella vettoriale in main.c imposta il relativo section attributo su .vector_table. Gli alias di script del linker CODE_REGION all'inizio di TCM o XIP e l'attributo ALIGN imposta l'allineamento della sezione di testo all'interno del file ELF come segue:

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

Considerazioni su tempo reale e latenza

RTApps e applicazioni di alto livello sostengono l'accesso alla memoria flash, anche se non comunicano tra loro. Di conseguenza, le RTApp in esecuzione da flash XIP possono riscontrare una latenza elevata e imprevedibile. Le scritture flash, ad esempio durante un aggiornamento, possono comportare picchi di latenza fino a diverse centinaia di millisecondi. A seconda dei requisiti dell'applicazione, è possibile gestirla in diversi modi:

  • Inserisci tutto il codice e i dati in TCM. Il codice eseguito da TCM non è vulnerabile alla contesa per flash.

  • Suddividi il codice in sezioni critiche e non critiche ed esegui il codice non critico da flash. Il codice che ha requisiti in tempo reale, ad esempio un timer di cane da guardia, non deve essere eseguito quando un altro codice accede al flash. I bersagli di memoria descrivono come target flash XIP invece di TCM.

  • Usare la cache. Un'applicazione può utilizzare il valore minimo di 32 KB di TCM come cache XIP. Questo approccio non offre garanzie in tempo reale difficili in caso di perdita della cache, ma migliora le prestazioni tipiche senza che sia necessario spostare tutto il codice nella RAM. Fare riferimento al "MT3620 M4 Datasheet" per informazioni sulla configurazione della cache XIP.