Partilhar via


Gerir considerações de memória e latência

Este tópico descreve considerações básicas de utilização da memória e latência para aplicações em tempo real executadas no chip MT3620.

Nota

Para obter mais detalhes sobre a configuração da memória ou o DMA, veja a Folha de Dados MT3620 publicada da MediaTek; Se as perguntas permanecerem, pode pedir a "Folha de Dados MT3620 M4" à Avnet ao enviar um e-mail para Azure.Sphere@avnet.com.

Esquema de memória nos núcleos em tempo real

A tabela seguinte resume a memória disponível nos núcleos em tempo real:

Tipo de memória Endereço Base
TCM 0x00100000
Flash XIP 0x10000000
SYSRAM 0x22000000

Cada núcleo em tempo real tem 192 KB de memória fortemente acoplada (TCM), que é mapeada em três bancos de 64 KB a partir de 0x00100000. Os acessos TCM são rápidos, mas apenas o núcleo em tempo real pode aceder à memória. O TCM não pode ser partilhado com uma aplicação de alto nível ou com uma aplicação com capacidade em tempo real (RTApp) que é executada num núcleo diferente.

Cada núcleo em tempo real também tem 64 KB de SYSRAM, que é mapeado a partir de 0x22000000. O controlador DMA também pode visar o SYSRAM, para que os periféricos possam aceder ao mesmo. Os acessos ao SYSRAM a partir do núcleo em tempo real são mais lentos do que os acessos ao TCM. Tal como acontece com o TCM, o SYSRAM não pode ser partilhado com outra aplicação.

A memória flash (XIP) no local é partilhada com aplicações de alto nível. Uma janela para o mapeamento XIP do flash é visível para cada núcleo no endereço 0x10000000. O SO configura o mapeamento XIP antes de iniciar a aplicação se o ficheiro ELF da aplicação contiver um segmento que tenha as seguintes propriedades:

  • O endereço de carga (conforme especificado na coluna VirtAddr do Cabeçalho do Programa) é igual a 0x10000000
  • O deslocamento e o tamanho do ficheiro (conforme especificado nos campos FileSiz e MemSiz no Cabeçalho do Programa) cabem no ficheiro ELF da aplicação

Se um cabeçalho de programa com estas propriedades estiver presente no ficheiro ELF da aplicação, a janela XIP será posicionada para que o segmento fique visível no 0x10000000. O ficheiro não pode ter mais do que um segmento XIP e tem de apontar para 0x10000000; não pode especificar qualquer outro endereço.

Implementação do ELF

As imagens RTApp têm de ser ficheiros ELF. A imagem ELF é encapsulada num pacote de imagem do Azure Sphere e implementada como uma aplicação. Para carregar a aplicação, o SO do Azure Sphere inicia um carregador ELF que é executado no núcleo em tempo real. O carregador processa cada segmento LOAD no ficheiro ELF e carrega-o para o tipo de memória indicado pelo endereço virtual no cabeçalho do programa.

Utilize arm-none-eabi-readelf.exe -l (lowercase L), que faz parte da Cadeia de Ferramentas GNU Arm Embedded, para apresentar os cabeçalhos de programa da sua aplicação. A coluna de endereço virtual (VirtAddr) que aparece no cabeçalho indica o endereço de destino do segmento de carga. Não significa que o próprio processador efetue qualquer tradução adicional. O carregador ELF do Azure Sphere não utiliza o endereço físico (PhysAddr).

Considere este exemplo:

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
  • O segmento em 0x00100000 destina-se a memória fortemente acoplada (TCM). O carregador copia dados do pacote de imagem para a RAM ou inicializa zero o TCM conforme necessário.

  • O segmento em 0x10000000 está mapeado para a janela XIP do núcleo. No tempo de execução, os acessos a são traduzidos para 0x10000000 + offset<address-of-XIP-segment-in-flash> + offset quando saem do núcleo em tempo real.

  • O segmento de dados na 0x00100e78 de endereços virtuais está mapeado para O TCM.

Considerações sobre o runtime do ELF

O carregador ELF executa algumas das tarefas que um binário não processado (ou um carregador de arranque em cadeia) executaria no arranque. Especificamente, inicializa zero dados block-started-by-symbol (BSS) e copia dados inicializados, mas mutáveis, do flash só de leitura para a RAM, de acordo com os cabeçalhos do programa. Em seguida, a aplicação inicia e executa as suas próprias funções de inicialização. Na maioria dos casos, não são necessárias alterações às aplicações existentes. Zeroing the BSS data in the application is unnecessary but harmless, because the loader has already zeroed the memory.

Copiar dados mutáveis do flash para a RAM pode, em algumas circunstâncias, resultar em problemas, consoante a forma como o ficheiro ELF é apresentado. O carregador ELF processa os cabeçalhos do programa sequencialmente, sem alterar o esquema geral dos segmentos no ficheiro. Em seguida, mapeia não só o segmento XIP para 0x10000000, mas também todos os segmentos subsequentes por ordem. Se os segmentos no ficheiro ELF estiverem por ordem sequencial sem qualquer alinhamento ou intervalo, o código de arranque do SO pode utilizar aritmética de ponteiro para encontrar o início do segmento de dados. No entanto, se o ficheiro ELF tiver um esquema diferente, a aritmética do ponteiro não resultará no endereço correto, pelo que o código de arranque da aplicação não pode tentar copiar a secção de dados. Isto pode causar problemas se a aplicação ou o RTOS utilizar um bootloader em cadeia ou precisar de configurar um canário de pilha antes de zeros BSS ou inicializar dados mutáveis.

Destinos de memória

Pode direcionar o código para TCM, XIP flash ou SYSRAM ao editar o script linker.ld da sua aplicação. As aplicações de exemplo do Azure Sphere são executadas a partir do TCM, mas o ficheiro de script linker.ld para cada aplicação descreve como direcionar o FLASH XIP. Como mostra o exemplo seguinte, pode alterar um exemplo para ser executado no XIP ao aliasar CODE_REGION e RODATA_REGION para FLASH em vez do TCM predefinido:

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

Para determinar se uma aplicação compilada é executada a partir do flash TCM ou XIP, utilize arm-none-eabi-readelf.exe, que faz parte da Cadeia de Ferramentas GNU Arm Embedded. Execute-o no ficheiro .out, que está no mesmo diretório que o pacote de imagem, e especifique o -l sinalizador (minúscula L) para ver onde o código e os dados só de leitura foram colocados. O código e os dados só de leitura que estão na memória flash são carregados no endereço 0x10000000; O código e os dados no TCM são carregados na região do TCM.

O exemplo seguinte mostra uma aplicação que é executada a partir da memória 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

Localização da tabela de vetores

Em dispositivos ARMv7-M, a tabela de vetores tem de estar alinhada num limite de potência de dois, que seja, pelo menos, 128 bytes e não inferior ao tamanho da tabela, conforme indicado no Manual de Referência da Arquitetura ARMv7-M. Cada núcleo de E/S no MT3620 suporta 100 interrupções externas. Por conseguinte, incluindo o ponteiro da pilha e 15 exceções padrão, a tabela tem 116 entradas de 4 bytes, para um tamanho total de 464 bytes, que arredonda até 512 bytes.

Quando o código é executado a partir do flash XIP, a tabela de vetores tem de ser colocada no 0x10000000 e tem de estar alinhada num limite de 32 bytes no ficheiro ELF. Quando o código não é executado a partir do flash XIP, a tabela é normalmente colocada no início do TCM0, que é 0x100000. Em ambos os casos, para garantir que o endereço virtual da tabela está corretamente alinhado, coloque a tabela de vetores numa secção dedicada e defina CODE_REGION para o endereço adequado.

Os exemplos de Mt3620 BareMetal no repositório de Exemplos do Azure Sphere mostram como fazê-lo. A declaração da tabela de vetores em main.c define o atributo section como .vector_table. Os aliases de script do linker CODE_REGION para o início do TCM ou XIP e o atributo ALIGN define o alinhamento da secção de texto no ficheiro ELF da seguinte forma:

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

Considerações em tempo real e latência

O RTApps e as aplicações de alto nível defendem o acesso à memória flash, mesmo que não comuniquem entre si. Como resultado, as RTApps executadas a partir do flash XIP podem encontrar latência elevada e imprevisível. As escritas a piscar, como durante uma atualização, podem envolver picos de latência até várias centenas de milissegundos. Consoante os requisitos da sua aplicação, pode geri-la de várias formas:

  • Coloque todo o código e dados no TCM. O código que é executado a partir do TCM não é vulnerável à contenção por flash.

  • Divida o código em secções críticas e não críticas e execute o código não crítico a partir do flash. O código que tem requisitos em tempo real, como um temporizador de cão de guarda, não deve ter de ser executado quando outro código está a aceder ao flash. Os destinos de memória descrevem como direcionar o flash XIP em vez do TCM.

  • Utilize a cache. Uma aplicação pode utilizar os 32 KB mais baixos de TCM como cache XIP. Esta abordagem não fornece garantias difíceis em tempo real em caso de falha de cache, mas melhora o desempenho típico sem exigir que mova todo o código para a RAM. Consulte a "Folha de Dados MT3620 M4" para obter informações sobre a configuração da cache XIP.