Existem diferentes segmentos de memória nos quais vários tipos de dados são inseridos no código C após a compilação. Ou seja:.text
, .data
, .bss
, pilha e heap. Eu só quero saber onde cada um desses segmentos residiria na memória do microcontrolador. Ou seja, quais dados entram em que tipo de memória, dado que os tipos de memória são RAM, NVRAM, ROM, EEPROM, FLASH etc.
Encontrei respostas para perguntas semelhantes aqui, mas elas não conseguiram explicar qual seria o conteúdo de cada um dos diferentes tipos de memória.
Qualquer tipo de ajuda é muito apreciada. Desde já, obrigado!
microcontroller
c
embedded
memory
Soju T Varghese
fonte
fonte
Respostas:
.texto
O segmento .text contém o código real e é programado na memória Flash para microcontroladores. Pode haver mais de um segmento de texto quando houver vários blocos não contíguos de memória Flash; por exemplo, um vetor inicial e vetores de interrupção localizados na parte superior da memória e código começando em 0; ou seções separadas para um programa de inicialização e principal.
.bss e .data
Existem três tipos de dados que podem ser alocados externos a uma função ou procedimento; o primeiro são dados não inicializados (historicamente chamados .bss, que também incluem os 0 dados inicializados) e o segundo é inicializado (não-bss) ou .data. O nome "bss" vem historicamente de "Block Started by Symbol", usado em uma montadora há 60 anos. Ambas as áreas estão localizadas na RAM.
À medida que um programa é compilado, as variáveis serão alocadas para uma dessas duas áreas gerais. Durante o estágio de vinculação, todos os itens de dados serão coletados juntos. Todas as variáveis que precisam ser inicializadas terão uma parte da memória do programa reservada para armazenar os valores iniciais e, pouco antes de main () ser chamado, as variáveis serão inicializadas, normalmente por um módulo chamado crt0. A seção bss é inicializada com todos os zeros pelo mesmo código de inicialização.
Com alguns microcontroladores, há instruções mais curtas que permitem o acesso à primeira página (primeiras 256 localizações, às vezes chamada página 0) da RAM. O compilador para esses processadores pode reservar uma palavra-chave
near
para designar variáveis a serem colocadas lá. Da mesma forma, também existem microcontroladores que podem apenas referenciar determinadas áreas por meio de um registrador de ponteiro (exigindo instruções extras), e essas variáveis são designadasfar
. Finalmente, alguns processadores podem endereçar uma seção da memória pouco a pouco e o compilador poderá especificar isso (como a palavra-chavebit
).Portanto, pode haver segmentos adicionais, como .nearbss e .neardata, etc., onde essas variáveis são coletadas.
.rodata
O terceiro tipo de dado externo a uma função ou procedimento é como as variáveis inicializadas, exceto que são somente leitura e não podem ser modificadas pelo programa. Na linguagem C, essas variáveis são indicadas usando a
const
palavra - chave Eles geralmente são armazenados como parte da memória flash do programa. Às vezes, eles são identificados como parte de um segmento .rodata (dados somente leitura). Em microcontroladores usando a arquitetura Harvard , o compilador deve usar instruções especiais para acessar essas variáveis.pilha e pilha
A pilha e o heap são colocados na RAM. Dependendo da arquitetura do processador, a pilha pode crescer ou diminuir. Se crescer, será colocado na parte inferior da RAM. Se crescer, será colocado no final da RAM. O heap usará a RAM restante não alocada para variáveis e aumentará a direção oposta da pilha. O tamanho máximo da pilha e da pilha geralmente pode ser especificado como parâmetros do vinculador.
Variáveis colocadas na pilha são quaisquer variáveis definidas em uma função ou procedimento sem a palavra-chave
static
. Eles já foram chamados de variáveis automáticas (auto
palavra-chave), mas essa palavra-chave não é necessária. Historicamente,auto
existe porque fazia parte da linguagem B que precedeu C, e era necessário. Os parâmetros de função também são colocados na pilha.Aqui está um layout típico para RAM (supondo que não haja uma seção especial na página 0):
EEPROM, ROM e NVRAM
Antes da chegada da memória Flash, a EEPROM (memória somente leitura programável apagável eletricamente) era usada para armazenar o programa e os dados const (segmentos .text e .rodata). Agora, há apenas uma pequena quantidade (por exemplo, 2 KB a 8 KB de bytes) de EEPROM disponível, se houver alguma, e é normalmente usada para armazenar dados de configuração ou outras pequenas quantidades de dados que precisam ser retidas durante a inicialização da inicialização. ciclo. Elas não são declaradas como variáveis no programa, mas são gravadas para o uso de registros especiais no microcontrolador. A EEPROM também pode ser implementada em um chip separado e acessada por um barramento SPI ou I²C.
A ROM é essencialmente a mesma do Flash, exceto que é programada na fábrica (não programável pelo usuário). É usado apenas para dispositivos de volume muito alto.
A NVRAM (RAM não volátil) é uma alternativa à EEPROM e geralmente é implementada como um IC externo. A RAM comum pode ser considerada não volátil se for feita com bateria; nesse caso, nenhum método de acesso especial é necessário.
Embora os dados possam ser salvos no Flash, a memória Flash possui um número limitado de ciclos de apagamento / programa (1000 a 10.000), portanto, não é realmente projetado para isso. Também exige que os blocos de memória sejam apagados de uma só vez, por isso é inconveniente atualizar apenas alguns bytes. Destina-se a variáveis de código e somente leitura.
A EEPROM tem limites muito mais altos nos ciclos de apagamento / programa (100.000 a 1.000.000), portanto é muito melhor para esse propósito. Se houver EEPROM disponível no microcontrolador e for grande o suficiente, é onde você deseja salvar dados não voláteis. No entanto, você também precisará apagar os blocos primeiro (normalmente 4KB) antes de escrever.
Se não houver EEPROM ou for muito pequeno, será necessário um chip externo. Uma EEPROM de 32 KB é de apenas 66 ¢ e pode ser apagada / gravada em 1.000.000 de vezes. Uma NVRAM com o mesmo número de operações de apagar / programa é muito mais cara (x10). As NVRAMs geralmente são mais rápidas para leitura do que as EEPROMs, mas mais lentas para gravação. Eles podem ser gravados em um byte de cada vez ou em blocos.
Uma alternativa melhor para ambos é a FRAM (RAM ferroelétrica), que possui essencialmente ciclos infinitos de gravação (100 trilhões) e sem atrasos de gravação. É aproximadamente o mesmo preço da NVRAM, cerca de US $ 5 por 32KB.
fonte
Sistema incorporado normal:
Além disso, geralmente existem segmentos flash separados para o código de inicialização e os vetores de interrupção.
Explicação:
Uma variável tem duração de armazenamento estático se for declarada como
static
ou se residir no escopo do arquivo (algumas vezes chamado de "global"). C possui uma regra informando que todas as variáveis de duração de armazenamento estático que o programador não inicializou explicitamente devem ser inicializadas como zero.Cada variável duração de armazenamento estático que é inicializado para zero, implícita ou explicitamente, acaba em
.bss
. Enquanto aqueles que são explicitamente inicializados com um valor diferente de zero terminam em.data
.Exemplos:
Lembre-se de que uma configuração não padrão muito comum para sistemas embarcados é ter uma "inicialização mínima", o que significa que o programa ignorará todas inicialização de objetos com duração de armazenamento estático. Portanto, pode ser aconselhável nunca escrever programas que dependam dos valores de inicialização dessas variáveis, mas defini-los no "tempo de execução" antes de serem usados pela primeira vez.
Exemplos dos outros segmentos:
Variáveis que podem ir para a pilha geralmente acabam nos registros da CPU durante a otimização. Como regra geral, qualquer variável que não tenha seu endereço utilizado pode ser colocada em um registro da CPU.
Observe que os ponteiros são um pouco mais complexos do que outras variáveis, pois permitem dois tipos diferentes de
const
, dependendo se os dados apontados devem ser somente leitura ou se o próprio ponteiro deve ser. É muito importante saber a diferença para que seus ponteiros não acabem na RAM por acidente, quando você queria que eles estivessem em flash.No caso de constantes inteiras, listas de inicializadores, literais de strings, etc., eles podem terminar em .text ou .rodata, dependendo do compilador. Provavelmente, eles acabam como:
fonte
.data
normalmente tem o chamado endereço de carregamento em flash, onde os valores iniciais são armazenados, e o chamado endereço virtual (não é realmente virtual em um microcontrolador) na RAM, onde a variável é armazenada durante a execução. Antes demain
iniciar, os valores iniciais são copiados do endereço de carregamento para o endereço virtual. Você não precisa armazenar zeros, portanto.bss
, não precisa armazenar seus valores iniciais. sourceware.org/binutils/docs/ld/…Embora qualquer dado possa entrar na memória escolhida pelo programador, geralmente o sistema funciona melhor (e deve ser usado) onde o perfil de uso dos dados corresponde aos perfis de leitura / gravação da memória.
Por exemplo, o código do programa é WFRM (escreva poucos leem muitos), e há muito disso. Isso se encaixa perfeitamente no FLASH. ROM OTOH é W uma vez RM.
A pilha e a pilha são pequenas, com muitas leituras e gravações. Isso caberia melhor na RAM.
A EEPROM não se adequaria bem a nenhum desses usos, mas se adequa ao perfil de pequenas quantidades de dados perisistentes nos power-ups, portanto, dados de inicialização específicos do usuário e talvez resultados de registro.
fonte