Desenvolvimento de Firmware: Introdução

Olá Habr! Apresento a você a tradução dos artigos de Chris Svec, o original está aqui . Publicado com permissão do autor sob licença CC-A-NC-ND .

Engenharia de software embarcada 101: introdução


Estou lançando uma série de tutoriais sobre desenvolvimento de firmware. Começaremos descrevendo um microcontrolador simples e, depois que você entender como ele funciona, iremos desenvolvê-lo para entender como ele funciona em relação a sistemas complexos, como Fitbit ou Nest.
Chamei essa série de Embedded Software Engineering 101, e começa esta semana aqui neste blog.

Continue lendo para mais explicações e detalhes.


Alguns blocos de construção em outros.

Trabalho com sistemas embarcados e desenvolvo microchips há mais de 14 anos. Gosto de sistemas embarcados - hardware, software e as limitações que os unem.
Eletrônicos amadores e idéias como Arduino , Adafruit e Sparkfun tornaram possível jogar facilmente algo de hardware e software no fim de semana (ou um mês ou semestre), criando algo novo, interessante e até útil.

É ótimo! Dar às pessoas a oportunidade de criar é uma coisa incrível; se quisesse me expressar com severidade, chamaria aspiracionalmente de "tecnologia democratizante".

A maioria dos projetos amadores é única. Você coleciona algo, torna-o tão bom quanto você tem tempo ou energia suficiente e segue em frente.
Passei minha carreira no extremo oposto do espectro - criando produtos com centenas de milhares ou milhões ou mais cópias - e isso requer uma maneira completamente diferente de pensar e uma abordagem sistemática.

Quero ensinar as pessoas a escrever firmware para esses tipos de sistemas. Alimentei essa idéia há muito tempo no curso / guia / livro / blog da Embedded Software Engineering 101 e, graças ao blog Embedded.fm, estou começando a implementá-la agora.

Como sou um tipo fundamental, meu plano é começar com o básico, com uma descrição simples de um microprocessador simples, e desenvolver essa base até você entender como funciona um sistema incorporado relativamente complexo.

Meu objetivo é que, ao final deste ciclo, você possa descobrir como o Fitbit funciona, um termostato Nest ou um sistema embarcado semelhante. Você pode começar a trabalhar com sistemas de software embarcados usando experiência profissional.

A Engenharia de software embarcada 101 foi projetada para:

  1. Graduados universitários no campo da ciência da computação, engenharia da computação ou eletrônica, interessados ​​em sistemas embarcados.
  2. Entusiastas de eletrônicos amadores que desejam entender mais profundamente como o sistema deles funciona no Arduino e descobrir como eles seguem em frente (e se é necessário!).
  3. , , .
  4. , , -.

O que quero dizer com dizer que sou uma “pessoa do tipo fundamental”? Richard Feynman , físico vencedor do Prêmio Nobel e excelente contador de histórias, colocou da melhor maneira possível: "O que não posso recriar, não entendo".

Portanto, não sou Feynman, mas tenho certeza de que a melhor maneira de entender o sistema é começar com o básico. Armado com esse entendimento, você pode criar sistemas embarcados simples com software simples. E, depois de entender um programa muito simples, você pode desenvolvê-lo criando software mais complexo à medida que a experiência aumenta.

O básico em primeiro lugar - é claro que isso é apenas minha convicção pessoal. Muitas pessoas fizeram coisas úteis com o Arduino sem entender nada do básico. Esta série de artigos é para aqueles que ainda querem entender o básico e tudo o que é construído sobre eles.

É claro que devemos nos perguntar - onde está o nível certo para começar com esses "princípios básicos"? Transistores e portas lógicas? Não, isso é muito baixo para começar com o firmware. Conectar-se a sensores comuns? Não, é um nível muito alto, é preciso muito conhecimento para começar com isso.

Eu acho que o nível certo de básico é o microprocessador embutido. Não é necessário entender física ou eletrônica para usar o microprocessador embutido; também não é necessário ser um especialista em programação.

Portanto, é aqui que começaremos no próximo artigo.

Aviso de preconceito: Em uma vida passada, eu era desenvolvedor de arquitetos / processadores. Iniciar esse ciclo entendendo como a CPU funciona pode não ser a melhor maneira de entender os sistemas incorporados, mas é assim que meu cérebro funciona. Tente outros cursos / manuais, etc., se você não entender isso depois de vários artigos.

Engenharia de software embarcada 101: noções básicas sobre microcontroladores


Começaremos nossa jornada do Embedded Software Egineering 101 com um microcontrolador modesto. Um microcontrolador (ou microprocessador) é o principal componente de todos os sistemas de computação, embutidos e outros.

O MK parece bastante complicado, mas consiste em três coisas simples: instruções, registros e memória. Instruções são as coisas que o microcontrolador sabe executar. Um MK simples é capaz de executar nem tanto - pode ter, por exemplo, 20 ou 30 instruções. Posteriormente neste ciclo, usarei o microcontrolador MSP430 da Texas Instruments, que possui apenas 27 instruções.


Apenas uma foto do MK (TI MSP430F5529)

Essas 27 instruções são as únicas coisas que o MSP430 pode fazer. Ele pode adicionar dois números, subtrair outro de um número, mover números de um lugar para outro ou executar 24 outras operações simples. 27 operações podem não parecer suficientes para fazer algo útil, mas, na realidade, serão suficientes para executar qualquer programa concebível.

Bem, isso significa que o microcontrolador tem instruções que fazem algo com números. Mas onde estão esses números? Registradores e memória! As instruções operam com números armazenados nos registradores e na memória.

Os registros são um repositório muito rápido que contém números que operam com instruções. Você pode pensar neles como um bloco de notas usado por instruções. O MK contém poucos registros, geralmente 8-32. Por exemplo, o MSP430 possui 16 registros.

A memória também armazena números, mas é muito maior e mais lenta que os registros. O microcontrolador pode ter 64 kB, 256 kB ou até mais de 1 MB de memória. MSP430F5529 tem cerca de 128 kB de memória; isso é mais de 8.000 vezes o número de seus registros!

Antes de começarmos a ver exemplos, peço que você pegue um pedaço de papel e uma caneta ou lápis e estude esses exemplos enquanto lê. É mais difícil estudá-los no papel do que apenas ler o que escrevi. Assim, você abordará cuidadosamente o processo, e as chances de memorizar os aprendidos serão maiores.

Vejamos um exemplo fictício, mas característico, de um microcontrolador.

Digamos que nosso MK tenha 4 registros e 8 células de memória. Os registros geralmente são chamados de forma criativa, por exemplo, "R0", "R1" etc. etc., e faremos o mesmo. As células de memória são geralmente referenciadas por seus números, também chamados de endereços de memória, começando pela numeração 0. É assim que nossos registros e memória ficarão:



E agora vou colocar alguns valores neles:



Agora, nosso microcontrolador fictício precisa de algumas instruções.
O conjunto de instruções que o MK conhece é chamado de conjunto de instruções. Digamos que no conjunto haverá três instruções: ADICIONAR (adicionar), SUB (abreviação de "subtrair" - subtrair) e MOVER (mover). As instruções devem obter os números dos quais eles operam de algum lugar e também colocar seus resultados em algum lugar, para que alguns deles contenham informações sobre onde estão os dados de entrada e saída.

Por exemplo, deixe nossa instrução ADD ter duas fontes e um receptor de dados, e todas elas devem ser registradoras. O manual pode descrever esta instrução assim:
ADD registr, regPrm
A instrução ADD adiciona o valor do registro regGist ao valor do registro regPrm e salva o resultado no registro regPrm
Resumo: regPrm = regGist + regPrm
Exemplo: ADD R1, R2 executa a operação R2 = R1 + R2
É geralmente aceito nas instruções para usar uma das fontes também como receptor, como a instrução ADD, usando regPrm como fonte e receptor de dados.

"ADD R1, R2" é uma linguagem assembler para um microcontrolador, é uma linguagem de programação nativa MK.

Vamos definir SUB no mesmo estilo:
SUB registr, regrpm
A instrução SUB subtrai o valor do registro registr do valor do registro regprm e armazena o resultado no registro regprm
Resumo: regPrm = regPrm - registr
Exemplo: SUB R3, R0 executa a operação R0 = R0 - R3
Por fim, deixe a instrução MOVE ter uma fonte e um receptor e:

  • ambos os argumentos são registradores,
  • um é um registro e um é um local de memória.

O guia do conjunto de instruções lerá:
1. MOVE registre, registre
2. MOVE registre, registre
3. MOVE registre, rem
A instrução MOVE copia os dados do argumento Leste para o argumento Prm.
Resumo: Existem três tipos de instruções MOVE
1. regPrm =
registr 2.regPm = memist
3. memPm = reg
Exemplo: Mostrarei exemplos da instrução MOVE posteriormente neste post.
Uma observação sobre a palavra “mover” usada para esta instrução: a maioria dos conjuntos de instruções a utiliza, embora, na realidade, os dados sejam copiados, não movidos.

O nome "mover" pode dar a impressão de que a fonte do operando da instrução é destruída ou limpa, mas, na verdade, permanece isolada, apenas o receptor é modificado.
Vamos examinar alguns exemplos usando nosso microcontrolador fictício.
No início, nossos registros e memória ficam assim:



Agora, executamos a seguinte instrução no MK:

ADD R1, R2

Ele pega o valor de R1, adiciona ao valor de R2 e armazena o resultado em R2. O processador executa a maioria das instruções em uma operação, mas dividirei a execução de cada instrução ADD, SUB e MOVE em várias etapas com a seta "=>" que conduz as substituições (registro / memória => valor):

R2 = R1 + R2 =>
R2 = 37 + 100 =>
R2 = 137

Após executar esta instrução, a memória permanece inalterada, mas os registradores agora têm a seguinte aparência, com o valor alterado escrito em vermelho:



Observe que R1 permanece inalterado; somente o registro do receptor R2 mudou.
Em seguida, vamos tentar a instrução SUB:

SUB R3, R0

Ela pega o valor de R3, subtrai-o do valor de R0 e armazena o resultado em R0:

R0 = R0 - R3 =>
R0 = 42 - 2 =>
R0 = 40

Depois de executar esta instrução, a memória permanece inalterada, mas os registros agora ficam assim:



Finalmente, vamos tentar algumas versões da instrução MOVE:

MOVE R2, R0

Esta instrução MOVE copia o valor de R2 para R0:

R0 = R2 =>
R0 = 137

E agora os registros ficam assim:



Em seguida, copiamos o registro na memória:

MOVE R3, [3]

Esta instrução MOVE copia R3 para o local da memória 3. Os colchetes no nosso conjunto de instruções são as células da memória.

[3] = R3 =>
[3] = 2

Os registradores permanecem inalterados, mas a memória muda:



E para o nosso último exemplo, copiamos o valor da memória para o registro:

MOVE [6], R0

Aqui, o valor da célula de memória 6 é copiado para o registro R0:

R0 = [6] =>
R0 = 1

A memória é imutável, e os registros agora têm a seguinte aparência:



acredite ou não, mas se você entende a maior parte do que acabamos de discutir sobre instruções, registros e memória, então entende os conceitos básicos de microcontroladores e linguagem assembly.

Claro que omiti muitos detalhes. Por exemplo, como o MK obtém instruções para executar?

Existem instruções mais interessantes do que apenas simples instruções matemáticas e de cópia? A memória é igual à RAM ou flash, ou não?

Responderemos a essas perguntas no próximo artigo.

All Articles