Por que precisamos de um gerenciador de inicialização separado do nosso aplicativo em microcontroladores?


28

Por que precisamos de um programa separado na mesma memória de programa flash de um microcontrolador, especificamente STM32F103, chamado de carregador de inicialização?

O que há de especial nisso para mantê-lo separado do programa aplicativo principal?

De um modo geral, um carregador de inicialização de um sistema baseado em microprocessador (por exemplo, PowerPC MPC8270) faz o mesmo trabalho que um microcontrolador (por exemplo, ARM STM32F103) ou eles executam tarefas fundamentalmente diferentes entre si e, ainda assim, são chamados de 'carregador de inicialização' ?


2
o mesmo motivo pelo qual você tem chips e peças individuais e não uma estrutura monolítica gigante
Emobe 03/07

Você não Basta entrar no seu programa com os interruptores e luzes no console do computador.
Hot Licks

1
A rigor, você não precisa de um programa de carregador de inicialização separado em um microcontrolador. Mas geralmente escolhemos um para as funções adicionais de utilidade que ele oferece. Se essas funções não forem necessárias, não desejadas, você poderá remover o carregador de inicialização. O carregador de inicialização do microcontrolador é normalmente usado para gravar um novo programa no flash. Às vezes, pode ser usado para funções de depuração, alguns pontos de interrupção de suporte e outras funções interessantes. Em um microcomputador, normalmente o carregador de inicialização carrega programas da memória de massa e será necessário lá.
ghellquist 04/07

Respostas:


55

Um carregador de inicialização em um microcontrolador é responsável por atualizar o firmware principal em um canal de comunicação que não seja o cabeçalho de programação. Isso é útil para atualizar o firmware em campo através de cartões BLE, UART, I2C, SD, USB, etc. Seria extremamente inconveniente exigir que os clientes adquirissem programadores apenas para atualizar o firmware em seus dispositivos.

A razão pela qual o gerenciador de inicialização é mantido separado é pela confiabilidade. O carregador de inicialização e o código do aplicativo são colocados em seções separadas do flash, para que o código do aplicativo possa ser apagado e reescrito pelo carregador de inicialização sem alterar nada relacionado ao código do carregador de inicialização.

Se o carregador de inicialização e o aplicativo fossem mantidos juntos, o código do carregador de inicialização precisaria ser copiado para a RAM antes de poder ser executado, pois qualquer atualização de firmware apagaria o código do carregador de inicialização em flash. Se a energia fosse cortada com o código do carregador de inicialização na RAM e o flash apagado, o dispositivo seria bloqueado.


3
A nossa é a mesma razão. Eles estão no mesmo flash, mas o carregador de inicialização é alinhado com os limites de apagamento do flash e inteligente o suficiente para apagar o flash apenas acima de seus próprios endereços.
Joshua

3
Em alguns casos, o cabeçalho de programação do microprocessador pode estar inacessível sem ter que desmontar o chassi do produto; portanto, reprogramar o barramento de comunicação sem o hardware extra é um fator essencial para a confiabilidade.
John Go-Soco

6
@ alt-rose O gerenciador de inicialização e o programa aplicativo são programas compilados separadamente, cada um com seu próprio código e main()função de inicialização . Ao ligar, o código de inicialização do carregador de inicialização é executado e chama o carregador de inicialização main(). O programa do carregador de inicialização verifica se há um aplicativo válido e, em seguida, pula para o código de inicialização do programa que chama o programa main(). O código de inicialização de cada programa inicializa o ambiente de tempo de execução C para o respectivo programa (ou seja, inicializa variáveis, pilha etc.) e, normalmente, nenhum dos programas main()retorna ao código de inicialização.
kkrambo 03/07

1
@ alt-rose: Da mesma maneira que a CPU obtém o endereço inicial do gerenciador de inicialização - não obtém. Em vez disso, a CPU especifica o que será usado como o endereço inicial do gerenciador de inicialização e o gerenciador de inicialização especifica o que será usado como o endereço inicial do programa aplicativo.
MSalters 04/07

4
@kkrambo Embora comumente verdadeiro, não há nenhum requisito (nem fato universalmente verdadeiro) de que um gerenciador de inicialização seja escrito em C ou em uma linguagem derivada de C com um main.
Yakk 04/07

26
  1. Para que o processo de carregamento possa se recuperar de erros. Suponha que haja um erro de comunicação ou desconexão de energia durante uma atualização. Se o carregador de inicialização fizesse parte do aplicativo que você estava atualizando, o usuário não poderá tentar novamente sem usar hardware especial para atualizar o carregador de inicialização.

  2. Alguns microcontroladores não podem executar código da RAM. Se o carregador de inicialização estivesse misturado com o restante do software, você não conseguiria atualizá-lo, porque não poderá apagar páginas de flash das quais está executando atualmente. A solução é primeiro gravar o novo código na segunda metade do flash e depois pular para ele. O novo código então se copia para a primeira metade do flash. É claro que a desvantagem é que o flash de gravação geralmente é lento e agora que você precisa fazer isso duas vezes, o processo de carregamento pode levar o dobro do tempo. Além disso, essa solução alternativa limita o tamanho do aplicativo a não ser maior que a metade do flash total.

  3. Carregadores de inicialização bem escritos tentam verificar se existe um código válido no dispositivo antes de tentar executá-lo. Se o carregador de inicialização e outro código foram combinados, como você pode ter certeza de que sua rotina de validação funcionaria se todo o código não fosse carregado?

  4. Autenticação. Os carregadores de inicialização seguros tentam verificar se o aplicativo carregado corresponde a uma assinatura digital antes de executar. Mas se o gerenciador de inicialização e outro código foram combinados, não será possível controlar o que é executado no dispositivo, porque, uma vez que o usuário carrega um novo código, não será possível controlar o que acontece na inicialização.


4
Como exemplo do ponto 2, alguns microcontroladores podem nem ter RAM acessível na inicialização: por exemplo, o Raspberry Pi usa sua GPU para carregar o gerenciador de inicialização de um cartão SD, que habilita o processador e a memória ARM.
ErikF

11

Eles geralmente estão lá para permitir que você atualize seu programa aplicativo principal.

Você precisa de um código que saiba como apagar e reprogramar parte do flash interno, que não pode ser o programa principal, pois quando ele é apagado, não seria possível reprogramar.


9

O carregador de inicialização permite que o MCU se comunique com outra coisa para aceitar um novo programa, armazená-lo e executá-lo após uma redefinição. Se você não possui um gerenciador de inicialização, é necessário um programador para acessar a memória e colocar o programa no lugar.


2
É praticamente isso. O MCU pode obter código apenas através de um subsistema de programação especial (como AVRICE ou JTAG) ou já tendo um gerenciador de inicialização em flash. É uma decisão do aplicativo quanto à complexidade do gerenciador de inicialização, por exemplo, alguns sistemas podem carregar o código do WiFi. Em MCUs de extremidade muito baixa, como um ATTiny, um gerenciador de inicialização (e pinos seriais) representa uma grande sobrecarga; portanto, você sempre usa um programador.
Rich

7

Além das outras respostas corretas sobre como permitir a reprogramação do firmware principal a partir do carregador de inicialização, outro benefício de separá-lo é que você pode separar logicamente as tarefas "executar uma vez na inicialização" do código necessário durante o tempo de execução. Então, depois que o carregador de inicialização concluir suas tarefas de configuração inicial, o firmware principal poderá despejar o carregador de inicialização com todo o código que não é mais necessário da memória, economizando espaço significativo na RAM. É possível fazer isso de outras maneiras, mas a divisão do carregador de inicialização / firmware facilita muito em muitas arquiteturas.


1
Em um microcontrolador, o código provavelmente nunca está na RAM, portanto não pode ser despejado. Você pode descartar os dados do carregador de inicialização da RAM, é claro.
Ben Voigt

@ BenVoigt, depende do microcontrolador. Alguns (principalmente aqueles com flash NOR) permitem executar diretamente sem flash, mas outros (geralmente com flash NAND, que está se tornando mais comum) exigem que você execute sem RAM. Às vezes, não há nenhum flash integrado, e você precisa copiar o código de um chip flash externo na SRAM local antes de poder executar qualquer coisa.
Nate S - Restabelecer Monica

2

A resposta curta é porque o software é incrível.

Você pode ter tudo o que o gerenciador de inicialização faz com "hardware puro". Mas é muito, muito, muito mais fácil ter as tarefas que o gerenciador de inicialização executa como software e depois interpretadas pelo hardware.

Essas tarefas podem envolver a configuração do hardware para a execução do software "real" (por exemplo, em um Raspberry Pi (via @ErikF)), com um protocolo para substituir o programa "real" antes da execução (verifique um pino, se esse pino é definido e reflash o programa real) ou até mesmo configurando o ambiente de software para o programa "real".

Em um software de menor escala, quando você executa um executável, o carregador de aplicativos move coisas como carregar partes dos dados na memória, às vezes corrige endereços, configura argumentos para coisas principais ou outras coisas globais, gira as bibliotecas fornecidas pelo sistema operacional e depois pula para o início do _maincódigo. Algumas dessas coisas podem ser feitas por um gerenciador de inicialização.

Em um microcontrolador, algumas das tarefas que um gerenciador de inicialização realiza podem ser divididas no programa. O compilador para sua plataforma pode injetar automaticamente o código de "configuração" em todos os executáveis.

Porém, tê-lo no carregador de inicialização significa que o mesmo compilador pode funcionar em hardware diferente, pois o carregador de inicialização pode "ocultar" a diferença entre as plataformas.

Além disso, o fato de um flash do programa principal não arriscar o gerenciador de inicialização (e a capacidade de atualizar o programa principal), e ter um gerenciador de inicialização não trivial é algo muito bom.


-1

Uma resposta que não foi abordada é a necessidade de separação de preocupações devido às limitações da linguagem C.

Geralmente, os gerenciadores de inicialização são escritos em uma mistura de Assembly e C, com o estágio de inicialização muito inicial no Assembly.

Isso é feito para configurar certas coisas como:

  • alocando a pilha C
  • lendo o ponteiro da pilha no registro
  • lendo o contador do programa no registro
  • declarando vetores de redefinição
  • carregando o segundo estágio (initramfs) na RAM.

Essa é uma aproximação muito aproximada das etapas executadas e estou descrevendo o processo de inicialização do ARM; é diferente novamente para x86 e outras arquiteturas.

No entanto, o principal motivo permanece o mesmo: a alocação da pilha C deve ser feita a partir da montagem.


Por que o voto negativo? Isso é relevante e preciso.
BitShift

-1

Uma parte da pergunta que ainda não foi respondida é a diferença entre os gerenciadores de inicialização nos microcontroladores e nos sistemas de microprocessadores.

Microcontrolador

A maioria dos microcontroladores possui memória ROM incorporada que contém o código do programa. A alteração desse código geralmente requer um dispositivo programador que se conecte à interface de programação do microcontrolador (por exemplo, ISP no ATMega). Mas essas interfaces de programação geralmente não são muito convenientes de usar, em comparação com outras interfaces, pois podem não estar prontamente disponíveis no contexto especificado. Por exemplo, enquanto quase todos os computadores possuem portas USB, a interface SPI necessária para o ISP é muito mais rara, e outras interfaces, como a interface PID usada no ATXMega, são suportadas apenas por hardware de programação dedicado.

Portanto, por exemplo, se você deseja atualizar o software de um computador comum sem nenhum hardware externo, pode usar um carregador de inicialização que lê de um tipo diferente de interface (por exemplo, RS232, USB ou RS232 através de USB como no Arduino) para programar o dispositivo sobre interfaces comuns.

Dito isto, se você não precisar dessa funcionalidade, o gerenciador de inicialização é completamente opcional. O microcontrolador ainda pode executar seu código completamente sem o gerenciador de inicialização.

Microprocessador

Em um microprocessador, as coisas são um pouco diferentes. Enquanto a maioria dos microprocessadores possui uma ROM grande o suficiente para um carregador de inicialização, essas ROMs não são grandes o suficiente para suportar um sistema operacional completo. Portanto, o objetivo do carregador de inicialização é inicializar o hardware, procurar um sistema operacional inicializável, carregá-lo e executá-lo. Portanto, o carregador de inicialização é essencial para cada inicialização.

Nos sistemas x86 / x64, esse carregador de inicialização é o BIOS ou o UEFI (basicamente uma versão mais recente de um BIOS).

Às vezes você pode até ter vários gerenciadores de inicialização executando em uma cadeia. Por exemplo, se você possui um sistema de inicialização dupla com Windows e Linux, pode acabar com o seguinte:

  • O BIOS / UEFI é inicializado e encontra o GRUB instalado. Em seguida, ele carrega o GRUB (= Grand Unified Bootloader)
  • O GRUB encontra algum tipo de Linux e o Windows Bootloader. O usuário seleciona o Windows Bootloader.
  • O carregador de inicialização do Windows é iniciado e encontra o Windows 7 e o Windows 10 instalados. O usuário seleciona o Windows 10.
  • Finalmente o Windows 10 é inicializado.

Portanto, neste caso, havia três softwares que podem ser considerados um gerenciador de inicialização. O GRUB e o Windows Bootloader estão disponíveis para oferecer ao usuário uma opção de seleção de inicialização mais conveniente do que a BIOS / UEFI daria a eles. Ele também permite o lançamento de vários sistemas operacionais a partir do mesmo disco rígido ou até da mesma partição.

TLDR

Portanto, enquanto nos dois sistemas o gerenciador de inicialização faz coisas semelhantes (ajudando o usuário a escolher qual código inicializar), ambos diferem bastante na maneira como realizam isso e no que fazem exatamente.


Embora seja útil distinguir sistemas com armazenamento não volátil (ROM ou flash) de acesso aleatório suficiente para manter o programa inteiro daqueles que precisam executar código da RAM, existem microcontroladores de ambos os tipos e microprocessadores de ambos os tipos.
supercat 04/07

Obviamente, a diferença entre um microcontrolador e um microprocessador não é uma fronteira rígida e alguns microcontroladores se comportam mais como um microprocessador e vice-versa. Por isso, tomei o AtMega / Arduino e o x86 / x64 como exemplos, porque eles se comportam dessa maneira.
Dakkaron

"os microprocessadores possuem uma ROM grande o suficiente para um carregador de inicialização ... Nos sistemas x86 / x64, esse carregador de inicialização é o BIOS ou o UEFI" Não. BIOS ou UEFI são armazenados na memória flash sem chip. A ROM no chip é para funções de nível ainda mais baixo, como a inicialização do microcódigo.
Ben Voigt

@Dkarkaron: eu traçaria a linha entre um microprocessador e um microcontrolador, com base no fato de o chip ser projetado para ser usado para fins não triviais sem qualquer outra coisa no barramento de endereço. O 8031 ​​não se qualificaria, exceto que é funcionalmente o 8051 (que é definitivamente um microcontrolador) que não é especificado como tendo algo útil na ROM interna, mas seria projetado para ser totalmente utilizável no armazenamento interno). Algo como um RCA / CDP 1802 não se qualificaria, embora possa ser usado para direcionar um crachá de LED ...
supercat

... sem RAM e ROM externa, porque os designs de RAMless / ROMless são limitados a tarefas triviais. Algo parecido com um TMS 32050 que, se bem me lembro, possui um gerenciador de inicialização e algumas milhares de palavras internamente, palavras de 16 bits da RAM se qualificariam como um microcontrolador; embora muitos aplicativos exijam mais adição de RAM, se conectados via UART a outro sistema, podem servir a muitos propósitos sem nada no barramento de memória.
supercat 5/07
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.