Gerenciar considerações sobre memória e latência
Importante
Esta é a documentação do Azure Sphere (Legado). O Azure Sphere (Legado) será desativado em 27 de setembro de 2027 e os usuários devem migrar para o Azure Sphere (Integrado) até esse momento. Use o seletor de versão localizado acima do sumário para exibir a documentação do Azure Sphere (Integrado).
Este tópico descreve o uso básico de memória e considerações de latência para aplicativos em tempo real executados no chip MT3620.
Nota
Para obter mais detalhes sobre configuração de memória ou DMA, consulte a Folha de dados MT3620 publicada da MediaTek, se ainda houver dúvidas, você pode solicitar a "Folha de dados MT3620 M4" da Avnet por e-mail.Azure.Sphere@avnet.com
Layout de memória nos núcleos em tempo real
A tabela a seguir resume a memória disponível nos núcleos em tempo real:
Tipo de memória | Endereço Base |
---|---|
MTC | 0x00100000 |
XIP flash | 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 acessar a memória. O TCM não pode ser compartilhado com um aplicativo de alto nível ou com um aplicativo com capacidade de tempo real (RTApp) que é executado em um 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 ter como alvo o SYSRAM, para que os periféricos possam acessá-lo. 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 Execute-in-loco (XIP) é compartilhada com aplicativos de alto nível. Uma janela para o mapeamento XIP do flash é visível para cada núcleo no endereço 0x10000000. O sistema operacional configura o mapeamento XIP antes de iniciar o aplicativo se o arquivo ELF do aplicativo contiver um segmento com as seguintes propriedades:
- O endereço de carregamento (conforme especificado na coluna VirtAddr do cabeçalho do programa) é igual a 0x10000000
- O deslocamento e o tamanho do arquivo (conforme especificado nos campos FileSiz e MemSiz no cabeçalho do programa) se ajustam ao arquivo ELF do aplicativo
Se um cabeçalho de programa com essas propriedades estiver presente no arquivo ELF do aplicativo, a janela XIP será posicionada de modo que o segmento fique visível em 0x10000000. O arquivo não pode ter mais de um segmento XIP e deve apontar para 0x10000000; não pode especificar qualquer outro endereço.
Implantação do ELF
As imagens RTApp devem ser arquivos ELF. A imagem ELF é encapsulada em um pacote de imagem do Azure Sphere e implantada como um aplicativo. Para carregar o aplicativo, o sistema operacional Azure Sphere inicia um carregador ELF que é executado no núcleo em tempo real. O carregador processa cada segmento LOAD no arquivo ELF e o carrega no tipo de memória indicado pelo endereço virtual no cabeçalho do programa.
Use arm-none-eabi-readelf.exe -l
(L minúsculo), que faz parte do GNU Arm Embedded Toolchain, para exibir os cabeçalhos do programa para seu aplicativo. A coluna de endereço virtual (VirtAddr) que aparece no cabeçalho indica o endereço de destino para o segmento de carga. Isso não significa que o próprio processador executa qualquer tradução adicional. O carregador ELF do Azure Sphere não usa 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 à memória fortemente acoplada (TCM). O carregador copia os dados do pacote de imagem para a RAM ou inicializa zero o TCM conforme necessário.
O segmento em 0x10000000 é mapeado para a janela XIP para o núcleo. Em tempo de execução, os acessos são
0x10000000 + offset
traduzidos para<address-of-XIP-segment-in-flash> + offset
quando saem do núcleo em tempo real.O segmento de dados no endereço virtual 0x00100e78 é mapeado para TCM.
Considerações sobre o tempo de execução do ELF
O carregador ELF executa algumas das tarefas que um binário bruto (ou carregador de inicialização encadeado) executaria na inicialização. Especificamente, ele zero-inicializa dados block-started-by-symbol (BSS) e copia dados inicializados, mas mutáveis, de flash somente leitura para RAM, de acordo com os cabeçalhos do programa. Em seguida, o aplicativo inicia e executa suas próprias funções de inicialização. Na maioria dos casos, as alterações nos aplicativos existentes não são necessárias. Zerar os dados BSS no aplicativo é desnecessário, mas inofensivo, porque o carregador já zerou a memória.
Copiar dados mutáveis do flash para a RAM pode, em algumas circunstâncias, resultar em problemas, dependendo de como o arquivo ELF é disposto. O carregador ELF processa os cabeçalhos do programa sequencialmente, sem alterar o layout geral dos segmentos no arquivo. Em seguida, mapeia não só o próprio segmento XIP para 0x10000000, mas também quaisquer segmentos subsequentes em ordem. Se os segmentos no arquivo ELF estiverem em ordem sequencial sem qualquer alinhamento ou lacunas, o código de inicialização do sistema operacional pode usar a aritmética de ponteiro para encontrar o início do segmento de dados. Se o arquivo ELF tiver um layout diferente, no entanto, a aritmética de ponteiro não resulta no endereço correto, portanto, o código de inicialização do aplicativo não deve tentar copiar a seção de dados. Isso pode causar problemas se o aplicativo ou RTOS usa um carregador de inicialização encadeado ou precisa configurar um canário de pilha antes de zerar o BSS ou inicializar dados mutáveis.
Alvos de memória
Você pode direcionar o código para TCM, XIP flash ou SYSRAM editando o script linker.ld para seu aplicativo. Os aplicativos de exemplo do Azure Sphere são executados a partir do TCM, mas o arquivo de script linker.ld para cada aplicativo descreve como direcionar o flash XIP. Como mostra o exemplo a seguir, você pode alterar um exemplo para ser executado no XIP aliando CODE_REGION e RODATA_REGION para FLASH em vez do TCM padrão:
REGION_ALIAS("CODE_REGION", FLASH);
REGION_ALIAS("RODATA_REGION", FLASH);
Para determinar se um aplicativo compilado é executado a partir do flash TCM ou XIP, use arm-none-eabi-readelf.exe
, que faz parte da GNU Arm Embedded Toolchain. Execute-o no arquivo .out, que está no mesmo diretório do pacote de imagem, e especifique o -l
sinalizador (L minúsculo) para ver onde o código e os dados somente leitura foram colocados. O código e os dados somente leitura que estão na memória flash são carregados no endereço 0x10000000; código e dados no TCM são carregados na região TCM.
O exemplo a seguir mostra um aplicativo que é executado 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 vetorial
Em dispositivos ARMv7-M, a tabela vetorial deve ser alinhada em um limite de potência de dois que seja de pelo menos 128 bytes e não inferior ao tamanho da tabela, conforme observado no Manual de Referência da Arquitetura ARMv7-M. Cada núcleo de E/S RT no MT3620 suporta 100 interrupções externas. Portanto, incluindo o ponteiro de pilha e 15 exceções padrão, a tabela tem 116 entradas de 4 bytes, para um tamanho total de 464 bytes, o que arredonda para 512 bytes.
Quando o código é executado a partir do flash XIP, a tabela vetorial deve ser colocada em 0x10000000 e deve ser alinhada em um limite de 32 bytes dentro do arquivo 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 esteja alinhado corretamente, coloque a tabela vetorial em uma seção dedicada e defina CODE_REGION para o endereço apropriado.
Os exemplos de BareMetal MT3620 no repositório de amostras do Azure Sphere mostram como fazer isso. A declaração da tabela vetorial em main.c define seu section
atributo como .vector_table
. Os aliases de script do vinculador CODE_REGION ao início do TCM ou XIP, e o atributo ALIGN define o alinhamento da seção de texto dentro do arquivo ELF da seguinte maneira:
SECTIONS
{
.text : ALIGN(32) {
KEEP(*(.vector_table))
*(.text)
} >CODE_REGION
...
}
Considerações sobre latência e tempo real
RTApps e aplicativos de alto nível disputam o acesso à memória flash, mesmo que não se comuniquem entre si. Como resultado, RTApps que estão sendo executados a partir do flash XIP podem encontrar latência alta e imprevisível. As gravações em flash, como durante uma atualização, podem envolver picos de latência de até várias centenas de milissegundos. Dependendo dos requisitos do seu aplicativo, você pode gerenciar isso de várias maneiras:
Coloque todo o código e dados no TCM. O código executado a partir do TCM não é vulnerável à contenção para flash.
Divida o código em seçõ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 vigilância, não deve ter que ser executado quando outro código está acessando o flash. Destinos de memória descreve como direcionar o flash XIP em vez do TCM.
Use cache. Um aplicativo pode usar os 32KB mais baixos do TCM como cache XIP. Essa abordagem não fornece garantias rígidas em tempo real no caso de uma falha de cache, mas melhora o desempenho típico sem exigir que você mova todo o código para a RAM. Consulte a "Folha de dados MT3620 M4" para obter informações sobre a configuração do cache XIP.