
1. Introdução
No momento, o mercado oferece uma ampla variedade de pagadores únicos para todos os gostos, a um preço acessível.
Como regra, vários conjuntos de fabricantes são projetados para avaliar a plataforma e são o ponto de partida de um novo projeto; portanto, eles nem sempre são adequados para tarefas específicas. Nas tarefas em que é necessária alta confiabilidade, o desenvolvedor enfrenta a questão de como finalizar o kit de distribuição e, em seguida, não paga por isso com uma revisão completa da imagem e do sistema de atualização.
Na Internet, quase não há informações sobre o que a versão deve ser compilada e como implementar sua atualização; portanto, o desenvolvedor é forçado a criar uma “bicicleta” ou usar seus próprios desenvolvimentos, que nem sempre são 100% testados.
Como participo do desenvolvimento de software para vários dispositivos Linux (meu portfólio pode ser google pela palavra develinux) e também sou autor do projeto de 11 partes, regularmente tenho que lidar não apenas com montagens de construção, mas também com o desenvolvimento de mecanismos de atualização via WEB ou USB flash.
Neste artigo, quero compartilhar minha experiência e conhecimento em áreas relevantes.
Requisitos de montagem
No processo de desenvolvimento de montagens e atualizações para vários dispositivos, identifiquei vários requisitos para mim:
- o conjunto não deve ser danificado quando a energia é desligada repentinamente;
- a montagem deve carregar rapidamente;
- o gerenciador de inicialização deve funcionar perfeitamente;
- assembly deve suportar atualização.
Tentarei explicar esses requisitos com mais detalhes abaixo e, depois disso, descreverei três abordagens na divisão de imagens em seções e suas atualizações.
O conjunto não deve ser danificado quando a energia for desligada repentinamente.
Quem precisa de um dispositivo que pare de funcionar após uma décima reinicialização? Para ninguém! Se você usar distribuições prontas (e existem muito poucas para incorporar), sem um arquivo da caixa, todas elas são muito pouco confiáveis nesse sentido. Lembrei-me muito bem do projeto em que usei o ubuntu sob imx6, os sistemas de arquivos no cartão estavam danificados, às vezes desde a décima reinicialização, às vezes a partir do quadragésimo, dependia das estrelas no céu. O projeto salvou FS aufs. O fato é que o ubuntu não foi projetado para somente leitura e deve sempre escrever algo. Lembro-me de uma situação semelhante em outro projeto em que o yocto foi usado em um cartão SD. Em geral, observe que os cartões SD são o tipo de unidade mais feio que causa o travamento mais rápido e muito mais confiável do que o emmc e o nand. Se você usa um cartão SD, é aconselhável escrever o mínimo possível durante a operação, os algoritmos de transferência em segundo plano para setores são muito imprevisíveis, trabalhei com dezenas de diferentes cartões SD de marcas mundiais e não encontrei um único cartão que eu pudesse recomendar.
Mas os cartões SD têm várias vantagens: são acessíveis, baratos e convenientes em software de depuração.
Por que estou ... E eis a questão - o FS raiz deve ser somente leitura, não deve haver nenhuma entrada durante a operação. Você provavelmente pensará: como? Milhões de dispositivos Android sempre escrevem algo e não falham. É verdade, mas tudo isso ocorre porque a maioria dos dispositivos Android, em primeiro lugar, tem uma bateria e, em segundo lugar, o FS raiz é enquadrado como ramdisk e a partição do sistema é somente leitura.
Se o sistema for confiável, todos os tipos de coisas com a instalação de pacotes no FS raiz podem estragar muito. Eu recomendo o squashfs como um sistema de arquivos. Funciona rápido, não pode escrever nada, economiza espaço devido à compressão ...
Mas e quanto a salvar configurações, baixar arquivos etc. você pergunta?
Mas, para isso, você precisa criar partições RW separadas. Se você planeja escrever em NAND, recomendo uma opção comprovada - UBIFS. Se estiver na NOR, então jffs2. Se eu escrever em outra unidade, recomendo ext4, btrfs, ReiserFS, não posso apontar o melhor FS entre eles, porque houve vários problemas com todos.
Nesse caso, sempre antes de montar partições rw, verifique se há erros nas partições usando utilitários do tipo fsck.
O conjunto deve carregar rapidamente
As velocidades de download do dispositivo afetam a usabilidade geral. Em algumas tarefas, o tempo de carregamento não é superior a 30 segundos; em alguns, 5 minutos são permitidos. Para mim, trabalhei até um minuto, quanto menos, melhor. Aguarde o download por mais de um minuto por muito tempo, pode parecer que o dispositivo travou; portanto, se você puder reduzir o tempo, é melhor usá-lo.
O carregador de inicialização deve funcionar sem problemas
O carregador é o que a montagem não começará sem. Recentemente, observei com freqüência como os fabricantes de placa única facilitam o desenvolvimento carregando uma demonstração de um cartão SD com uma descrição de como registrar um carregador de inicialização ou uma imagem finalizada em um carregador de inicialização, que é simplesmente preenchido com o comando dd. Mas e se o cartão SD congelar? O mesmo não é incomum. Pessoalmente, na minha prática, as cartas caíam frequentemente. É assim que você trabalha por uma taxa por várias horas, escreve software, bam e isso é tudo ... erros no kernel começam a aparecer, o cartão caiu. Mas e se esse for um dispositivo que funcione nos campos sem reiniciar? A propósito, reiniciar incluindo watchdog nem sempre revive um cartão travado, o cartão não tem um sinal de redefinição, isso não é emmc, é claro que isso é mais uma questão para o circuito da placa, se a placa tiver uma redefinição do poder da placa, isso economizará, mas isso não está em toda parte. Em algumas placas, apenas distorcer a energia ou o cartão ajuda. Com base na minha experiência, não recomendo armazenar o carregador de inicialização na unidade com o conjunto principal se a gravação for realizada na unidade durante a operação. Se o sistema não gravar nada na unidade com o gerenciador de inicialização, e isso raramente acontecer, por favor. Na minha experiência, no modo somente leitura, o sistema de arquivos foi deformado apenas devido a erros de hardware, mas não a erros de software.
O carregador de inicialização deve ser armazenado em um local seguro, em uma unidade confiável, por exemplo, em um chip NOR ou EEPROM separado. Abaixo está um exemplo de módulo baseado no chip imx6ull, com SPI NOR para armazenar o gerenciador de inicialização.
A construção deve suportar a atualização
Sem uma atualização, lugar nenhum ... Participei de muitos projetos e nunca obtive o software perfeito para a entrega do trabalho. Sempre é detectado um erro ou é necessária uma melhoria funcional. Você precisa entender que, enquanto as pessoas escrevem software, elas cometem erros, enquanto as pessoas usam o dispositivo, elas querem um pouco mais. Em 90% dos casos, a falta de um sistema de atualização bem pensado pode levar à dor de cabeça do fabricante e ao colapso de todo o projeto. Por exemplo, um sistema de videovigilância foi desenvolvido para transporte, o sistema foi instalado em toda a Rússia e verifica-se que os profissionais de marketing subestimaram o mercado e não forneceram streaming. Além disso, foram encontrados vários erros no firmware, além de o consumidor começar a olhar na direção dos concorrentes, porque eles há apenas algo que não está no dispositivo adquirido ... Sim, sim, em um jardim estranho os morangos são mais saborosos e o clima é melhor (psicologia).
O que fazer em tal situação? Se a atualização for suportada, existem muitas soluções, erros podem ser corrigidos, transmissão de fluxo pode ser melhorada e a funcionalidade pode ser personalizada para o consumidor, fornecer instruções ao firmware do consumidor e isso é tudo. Mas se não for suportado, o fabricante terá grandes aventuras com viagens de negócios de engenheiros de serviço até a substituição de dispositivos.
O sistema de atualização no dispositivo deve ser pensado nos mínimos detalhes e testado 100%. Um erro nesta parte transformará o ferro em tijolo, portanto não deve haver tolerâncias e exceções.
O processo de atualização deve ser resistente ao desligamento da energia e, sob nenhuma circunstância, deve estragar o dispositivo.
Uma visão geral das abordagens de particionamento para atualizações futuras
Das muitas abordagens, posso recomendar três tipos que eu implementei pessoalmente. Essas não são todas as abordagens; seu escopo está além do escopo deste artigo. Todos os três tipos têm falhas e estão longe do ideal, mas, como me parece, estão próximos da média de ouro do senso comum.
Abordagem No. 1
A maneira mais fácil e acessível:
Uma imagem é colocada em uma unidade, por exemplo, um cartão SD, que é exibido a partir do u-boot na unidade interna do dispositivo, por exemplo, flash NAND.
No u-boot, você precisa preparar scripts para isso.
Dos benefícios - este é o tipo mais fácil de atualização, cujo desenvolvimento levará no máximo 1 dia.
As desvantagens dessa abordagem são a falta de visualização do processo e os recursos muito limitados do gerenciador de inicialização, ou seja, não há lógica complicada com ferramentas padrão, a menos que você crie seu próprio comando u-boot (mas esse é outro tipo de atualização, C é uma grande força). Esse método não se destina a atualizações via WEB - é problemático controlar a integridade da imagem do firmware; em alguns casos, o tamanho da montagem não deve exceder o tamanho da RAM.
Além disso, em algumas tarefas é necessário salvar as configurações durante a atualização, e isso, com essa abordagem, não é fácil de implementar.
Abordagem No. 2
O método mais confiável e protegido do considerado, mas o mais difícil. Eu recomendo que esse método seja usado em desenvolvimentos especialmente responsáveis, como Ele protege as imagens quebradas e os danos físicos ao inversor principal, uma vez que o circuito usa um adicional.
A abordagem usa uma compilação mínima (tamanho de ramdisk de 8 a 16 MB) e a principal. O Ramdisk é um arquivo compactado, portanto uma compilação de 16 MB será fisicamente várias vezes menor.
O objetivo de uma montagem mínima é avaliar a montagem principal e carregá-la.
O Ramdisk é hospedado com os scripts do kernel e do u-boot em uma imagem FIT.
Por que a imagem FIT e o que ela fornece? A imagem FIT é um formato suportado pelo u-boot. Garante a integridade de todos os componentes (kernel, dts, ramdisk, scripts). A descompactação da imagem FIT é realizada no u-boot e, se a soma de verificação não convergir, o u-boot se recusará a carregá-lo. Isso é conveniente, ou seja, não há necessidade de cuidar do controle de integridade sozinho, não há necessidade de gravar vários arquivos separadamente ou inventar suas próprias imagens, tudo é feito pela imagem FIT. Geralmente, uma imagem FIT ocupa de 7 a 20 MB; ela deve ser gravada em uma unidade altamente confiável, por exemplo, em qspi ou flash. O conjunto principal pode ser armazenado em memória mais barata e não confiável, por exemplo, flash NAND. Como o trabalho principal ocorrerá na montagem principal, é precisamente isso que será danificado primeiro. Nesse caso, uma unidade separada com o mínimo de rootfs será resgatada.
Processo de inicialização.
O u-boot baixa um script que tenta usar as atualizações do FIT (FIT2) e, em seguida, o firmware de fábrica do FIT (FIT1).
Se o FIT2 não estiver presente ou sua integridade for violada, o teste de ajuste falhará e o u-boot carregará o primeiro FIT (FIT1). Se houver atualizações do FIT (FIT2) e não estiver danificado, o seu ramdisk será carregado para verificar as atualizações do rootfs (Rootfs2).
Se o Rootfs2 estiver quebrado, os scripts excluirão as atualizações do FIT (FIT2); depois da reinicialização, a imagem de fábrica que consiste em FIT (FIT1) e Rootfs1 será baixada.
Processo de atualização.
A imagem de atualização contém FIT, rootfs e várias informações de montagem, incluindo somas de verificação de todos os seus componentes. As informações de montagem são usadas durante a atualização para monitorar a integridade e a compatibilidade.
Atualize o progresso nas etapas:
- verificação da imagem quanto à compatibilidade com hardware e software,
- verificar a integridade da imagem no arquivo de atualização,
- copiar Rootfs2 do arquivo de atualização para uma seção preparada anteriormente,
- verificar a integridade da imagem copiada na seção,
- copie o FIT2 para a seção apropriada,
- reiniciar.
Se o processo falhar, a ausência ou dano do FIT2 não arruinará o sistema, pois O u-boot simplesmente se recusará a usá-lo e carregará a imagem de fábrica. Portanto, durante a atualização, a integridade do FIT2 não é verificada.
Após a atualização, o novo assembly será colocado na unidade principal na forma de FIT2 e Rootfs2.
Este método é resistente a danos mecânicos no inversor e erros de FS.
Em caso de mau funcionamento crítico, a imagem de fábrica será iniciada, onde o software de recuperação funcionará, o que, por exemplo, pode verificar novamente a NAND, fazer o download do firmware da rede usando o protocolo SSH e depois gravá-lo.
Dei apenas um exemplo de recuperação, há muitas opções. Nesta abordagem, o processo de recuperação é conduzido pelo Linux completo, que pode fazer tudo ... e não o gerenciador de inicialização, como na primeira versão.
Abordagem No. 3
Esse tipo de atualização é usado em quase todos os projetos de 11 partes, pois funcionou muito bem.
A atualização é adequada para qualquer tamanho de montagem, para qualquer tipo de unidade. Diferente do tipo anterior, aqui o SPI NOR é usado apenas para u-boot, portanto, possui um tamanho menor e um custo menor, 1 MB é suficiente.
Esse tipo de atualização não requer uma compilação separada do ramdisk, o que significa que o tempo de programação é economizado para seu desenvolvimento e suporte no futuro.
O exemplo usa uma unidade de cartão SD, mas também pode ser NAND usando UBIFS, sem diferença. Nesta abordagem, não há verificação do Rootfs RO antes do carregamento; se o conjunto estiver danificado, o sistema não saberá que foi danificado e o carregará em um círculo. Aqui supõe-se que os dados na seção RO não possam ser alterados de forma alguma, essa abordagem elimina o mau funcionamento físico do inversor. Se a unidade não estiver fisicamente saudável, o dispositivo deverá ser transportado para um centro de serviço, não será fornecida autocorreção. Este é o preço que você deve pagar para aumentar a velocidade de desenvolvimento, o suporte mais barato e a base elementar mais barata, mas isso é justificado. Por que segurar contra algo que quase nunca acontece.
A lógica para baixar e atualizar é a mesma da abordagem anterior.
No caso de carregamento, o u-boot baixa primeiro as atualizações do FIT (FIT2); se ele não existe ou a integridade é violada, o u-boot carrega o primeiro FIT (FIT1), o conjunto que foi costurado na fábrica é iniciado e assim sucessivamente até que o sistema seja atualizado. Quando o sistema é atualizado, o FIT2 e o Rootfs2 aparecerão. Nesse caso, quando o dispositivo inicializa, a atualização do FIT (FIT2) inicia primeiro. Nos scripts u-boot armazenados em cada FIT, deve ser escrito quais rootfs montar.
Partição compartilhada RW
Nos gráficos, há um bloco de partição compartilhado em todos os lugares, este é um grupo de seções para gravação. Quaisquer entradas são feitas apenas lá. Partição compartilhada é mostrada como uma partição para maior clareza. De fato, existem três deles: dois pequenos para configurações que funcionam no espelho e um grande para todo o resto. Além disso, recomendo que você mantenha algumas das configurações ao atualizar, o que é conveniente, por exemplo, se você configurar a rede e atualizar, não precisará reconfigurar as configurações de rede.
Resumir
O artigo discute três tipos de montagens com suporte para atualizações, todas verificadas pessoalmente por mim; você pode usá-las com segurança em projetos.
No momento, uso apenas os dois últimos, pois são mais adequados para os requisitos. Para maior clareza, você pode ver exemplos de dispositivos nos quais esses tipos de atualizações são usados (detalhes no portfólio de 11 partes):
- Repetidor RS485 via 4G / WiFi / LAN,
- Placa de controle industrial do controlador da exposição 4K V-By-One,
- sistema integrado de controle climático do hangar,
- 2DisplayPort-LVDS controlador de vídeo de exibição industrial,
- sistema de controle de linha
- Gateway de VPN.
Se meu artigo for útil e interessante, estou pronto para compartilhar ainda mais minha experiência e soluções técnicas comprovadas no campo do linux incorporado neste site.
Obrigado a todos.
Gorchakov Ilya
telegrama:
develinux