Uma das coisas legais dessa placa é a abundância de informações e coisas prontas. A Atmel fornece os fontes do bootstrap, o U-Boot e o kernel do Linux também a suportam. Podemos baixar e instalar os programas e ferramentas, podemos baixar um ambiente pronto ou podemos construir a própria infraestrutura, e é isso que vou descrever neste texto. Esta é uma coleção de scripts, não um repositório de fontes de programas e bibliotecas, por isso, os scripts foram construídos para fazer o download dos fontes, preferencialmente a partir dos sites oficiais. Entretanto, alguns programas tem pequenos bugs ou precisam de algum tipo de adaptação e, nesse caso, arquivos contendo as correções/alterações (patches) são fornecidos. Às vezes são necessárias ferramentas de apoio que não existem e precisaram ser construídas por mim, os fontes são fornecidos com licença GPL 3.0.
Mas, antes de continuar, um aviso: Os sistemas/scripts construídos tem fins didáticos, embora a utilização para quaisquer outros fins, dentro da lei, seja livre, não há nenhuma garantia de funcionamento, como devidamente explicado na licença GPL3. A licença dos scripts é GPL3, a menos que esteja especificado o contrário no cabeçalho, a licença dos textos é FDL 1.3. As licenças dos programas-fonte é a que está publicada em cada um deles. Se usar qualquer parte deste texto como referência para cursos, palestras, projetos, trabalhos, outros artigos ou qualquer outra utilização legal, seja educado e mencione a fonte. Se possível, gostaria de ser avisado. Os scripts funcionaram no Ubuntu 10.10.
A primeira coisa a fazer é construir as ferramentas necessárias para poder compilar os outros programas. Depois, vamos compilar os programas construídos para o Tabajara Linux para que funcionem nessa CPU. Quanto mais "para baixo", maior é a diferença entre as plataformas. O bootstrap e o U-boot são específicos para a placa. O toolchain e a libc também tem que ser modificados para funcionar com ARM. Já os programas de nível mais alto dificilmente precisarão ser modificadas, basta compilar e vai estar pronto para usar. Resumindo, uma vez que as ferramentas de compilação e os programas para inicialização do hardware estiverem funcionando, em tese qualquer programa poderá ser compilado para funcionar no Tabajara ARM Linux. Em tese, é claro.
Começando pelo começo, do ponto de vista da inicialização, quando a placa é ligada ou resetada, um programa que está gravando na ROM interna entra, e tenta detectar, carregar para a SRAM e executar um programa contido na dataflash, se não der certo, tenta o mesmo na NANDFlash, e, por último, tenta encontrar um arquivo chamado boot.bin num SD card. Se, ainda assim, nada for encontrado, a EEPROM é vasculhada. Se não houver um programa na EEPROM, o SAM-BA é iniciado e fica esperando uma transação pela porta USB device ou na porta DBGU.
O protocolo do SAM-BA é ridiculamente simples, mas por hora é melhor usar a ferramenta pronta fornecida pela Atmel. Ela carrega um programinha na SRAM, dependendo do tipo de operação, e executa-o. Existe um programa para gravação na NAND, outro para a Dataflash, etc. Essa aplicação também permite executar um script TCL para automatizar as operações, mas infelizmente sou analfabeto em TCL. Já falei sobre o SAM-BA anteriormente, vale a pena dar uma olhada lá.
O U-boot é um programa sensacional capaz de funcionar em um quantidade enorme de processadores e placas, é um programa monitor com um shell simples, e também é um boot loader capaz de carregar e inicializar diversos tipos de kernel, entre eles o Linux. O kernel pode ser carregado a partir de Bootp, TFTP, NFS, Storage Device ligado na porta USB, porta serial usando protocolo Xmodem e, obviamente, NAND flash, NOR, eeprom, etc. Durante a fase de desenvolvimento é mais fácil e produtivo usar o U-boot para carregar o kernel e o sistema de arquivos a partir da rede, evitando a regravação da flash e ficar toda hora precisando usar a ferramenta SAM-BA. Quando o desenvolvimento estiver mais estável, o kernel e o sistema de arquivos podem (devem?) ser gravados na flash.
O kernel do Linux será configurado para suportar todos os periféricos da placa, e ainda alguns dispositivos USB, como câmeras, wi-fi dongle, etc. Além disso, é mais fácil adicionar tudo e depois retirar o que não vai ser usado. Além das ferramentas básicas, vários programas serão compilados, como o UDev, o links e o wpa_supplicant.
Melhorias nos scripts
Com o aumento na quantidade de ferramentas, bibliotecas e utilitários, foi necessário criar um sistema para verificar as dependências entre eles. Sem isso, pode ser que o build não termine ou, ainda pior, que compile incorretamente. Também foi adicionado um modo de instalar dependências de binários. A filosofia é que cada script é responsável de instalar tudo que for necessário para funcionar corretamente. Como o i586, montamos um espelho do sistema de arquivos que vai ser usado, com todos os diretórios e arquivos. Entretanto, não usamos a habilidade de instalar que vem com os programas, porque eles instalam muitas coisas além do básico (por exemplo, exemplos, testes, documentação, etc), e queremos somente os binários e nada além do que for estritamente necessário. Por isso, usamos o instalador embutido para instalar tudo no diretório da arquitetura (onde estão os compiladores) e copiamos somente o que nos interessa para o diretório raiz do novo sistema de arquivos. Quando o sistema de arquivos estiver com todas os programas instalados, ele pode ser copiado, do jeito que está, diretamente para um dispositivo, por exemplo, um cartão de memória, ou, ainda, poderemos gerar uma imagem de um sistema de arquivos que pode ser copiada para um dispositivo. Também poderemos exportar o diretório e montar via rede.
Toolchain
O mesmo conjunto de scripts que usado para construir o TBJ/i586 será usado para o TBJ/at91, com algumas pequenas modificações. A glibc, por exemplo, não é oficialmente suportada na arquitetura ARM, o suporte é fornecido através de um plugin. O binutils tem um bug no as, que aparece quando compilando no gcc 4.4, e que precisa ser consertado, o script aplica um patch para consertar. Já o gcc compila sem problemas.
UDev
O uso do Udev é questionável para sistemas embutidos, mas ele pode ser útil em certas situações, por exemplo, se for permitido adicionar/remover dispositivos via USB. De qualquer forma, remover o UDev é simples: basta não iniciar o daemon. No kernel selecionamos a opção de montar o /dev automaticamente, o que evita a necessidade de termos um script para criar os devices na inicialização. No diretório /etc/scripts existem alguns shell scripts que foram construídos para serem executados quando um determinado tipo de hardware for detectado. Alguém poderá alegar que isso é justamente o que o UDev faz, mas não com shell scripts.
Scripts de inicialização
Uma pequena alteração nos scripts: para ficar mais parecido com um SystemV tradicional, movi os scripts para "/etc/init.d" e usei links para inicializar (começando com S) e finalizar (começando com K). Os scripts detectam se a intenção é iniciar ou finalizar, e também aceitam os tradicionais start/stop, se passados como parâmetro da linha de comando. Os scripts ainda precisam ser melhorados, mas a infraestrutura está razoavelmente estabelecida.
Plataforma "generic"?
Na primeira tentativa, copiei todos os scripts desenvolvidos para o i586 e fui alterando para que funcionassem no AT91. Entretanto, logo ficou claro que a maioria dos scripts podem ser usados sem qualquer modificação em mais de uma plataforma, exceto, é claro, as informações da arquitetura alvo e o compilador. Por isso, movi todos os scripts comuns para o diretório "generic", junto com o template comum de root e o script de funções comuns.
Árvore de Diretórios
Após essas adaptações e melhorias, a árvore de diretórios ficou assim:
| tbj | |||||
| scripts | |||||
| generic scripts que (teoricamente) servem para qualquer plataforma. | |||||
| common.sh script com funções de uso geral. | |||||
| app scripts para compilar os programas. | |||||
| base scripts para compilar o kernel e o busybox. | |||||
| lib scripts para compilar as bibliotecas. | |||||
| root arquivos com templates para montagem de sistema de arquivos, genéricos. | |||||
| toolchain scripts para geração do toolchain (compilador, linker, libc, etc). | |||||
| armat91 scripts para plataforma ARM AT91 | |||||
| all.sh script para compilação de todos os scripts. | |||||
| vars.sh script que define as variáveis da plataforma. | |||||
| app scripts para compilar programas. | |||||
| base scripts para compilar o kernel e o busybox. | |||||
| buildcontrol diretório onde é mantido o controle de compilação e versões. | |||||
| lib scripts para compilar as bibliotecas. | |||||
| preboot scripts para construir ferramentas de pré-boot. | |||||
| root arquivos com templates para montagem de sistema de arquivos, específicos para a plataforma. | |||||
| toolchain scripts para geração do toolchain (compilador, linker, libc, etc). | |||||
| utils utilitários diversos (sam-ba, scripts). | |||||
| i586pc scripts para plataforma i586 | |||||
| (Repete a estrutura do diretório armat91) | |||||
| arm-at91-linux-gnu Criado durante o build, tudo o que for produzido pelos scripts do diretório armat91 ficará nesse diretório. | |||||
| bin diretório dos executáveis do toolchain, também pode servir para instalação de algum utilitário que precise ser colocado no diretório /bin. Por enquanto somente programas pertencentes ao toolchain são colocados aqui. | |||||
| build diretório onde os programas e bibliotecas são compilados. Alguns programas não conseguem ser compilados em um diretório diferente do diretório onde estão os fontes, quando isso acontece, para manter o padrão, um soft link é criado neste diretório, apontando para o diretório real dos fontes. | |||||
| arm-at91-linux-gnu algumas bibliotecas do GCC são colocadas neste diretório | |||||
| lib diretório de instalação das bibliotecas, corresponde ao /lib. | |||||
| root Este não é o diretório do usuário root, mas o root da imagem do novo sistema de arquivos. Má escolha de nome. | |||||
| src contém os fontes dos diversos programas e bibliotecas. | |||||
| usr diretório de instalação dos programas e bibliotecas, corresponde ao /usr. | |||||
| i586-tbjpc-linux-gnu Criado durante o build, tudo o que for produzido pelos scripts do diretório i586pc ficará nesse diretório. | |||||
| (Repete a estrutura arm-at91-linux-gnu) | |||||
| tar arquivos-fonte compactados. | |||||
Boot
É necessário um pequeno programa de inicialização que prepara o hardware e carrega um outro programa. Esse programa tem de ser mínimo e agnóstico, e tem de saber conversar com o hardware para poder prepará-lo. Ainda bem que a Atmel fornece os fontes de um programa de inicialização, já que não somos especialistas no hardware e construir o programa de inicialização do zero poderia ser um pouco trabalhoso. Com os fontes do programa em mãos, poderemos fazer algumas modificações. Sem alterações, o programa fornecido pela Atmel faz o seguinte:
- Inicializa o hardware e o controlador de memória
- Lê 1 bloco de dados da memória flash (NAND ou NOR, dependendo do fonte escolhido) para a RAM
- Executa o programa carregado (um simples jump para o endereço de carga)
U-Boot
O programa de inicialização pode carregar um outro programa intermediário ou o kernel do Linux diretamente. Esse "programa intermediário" pode ser, por exemplo, o U-Boot. Ele tem suporte já pronto para diversas placas, incluindo a nossa, digo, do Fernando, e é capaz de usar a USB, o LCD, as portas seriais, as Flashes, e, muito importante, a ethernet. Além de "entender" o hardware, o U-Boot traz suporte pronto para fazer o download de programas pela serial usando XModem, pela ethernet usando tftp ou nfs, e a inicialização pode ser feita com IP fixo ou dinâmico usando DHCP ou bootp. Podemos definir o funcionamento do U-Boot facilmente usando "variáveis de ambiente" que são carregadas quando o U-Boot é iniciado. Podemos modificar o conteúdo das variáveis e executar alguns comandos para inspecionar o hardware usando um shell simples, acessado via porta serial. Com toda essa flexibilidade, o U-Boot é altamente recomendado durante a fase de desenvolvimento, e muitas empresas distribuem seus produtos com o U-Boot em produção. A desvantagem é perder um pouco do espaço em flash.
O script que compila o U-Boot e gera os arquivos no formato correto para serem gravados na flash é o bootloader/2-uboot.sh. Defina as variáveis de ambiente SERVERIP e DEVICEIP no arquivo bootloader/3-uboot_gen_files.sh para os endereços IPs fixo do servidor NFS e do dispositivo. A variável CMDLINE_NFS deve conter a linha de comando a ser passada pelo kernel. Se usado como está, o endereço IP do servidor está definido como 192.168.20.1 e o do device é 192.168.20.100.
Formato do kernel
O kernel precisa estar no formato esperado pelo U-Boot. Felizmente, junto com os próprios fontes do Ubuntu vem uma ferramenta capaz de criar um arquivo no formato correto, é o mkimage, que é corretamente chamado pelo programa bootloader/3-uboot_gen_files.sh.
U-Boot carregando o kernel e o sistema de arquivos na flash
Para essa opção, execute o script bootloader/scripts/uboot-nand-nand.tcl pelo SAM-BA. Essa opção é ideal para usar o U-Boot em produção. O layout da nand flash será o seguinte:
| Endereço | Conteúdo |
| 0x00000000 | Bootloader |
| 0x00020000 | U-Boot |
| 0x00080000 | U-Boot Environment |
| 0x000A0000 | Kernel |
| 0x00400000 | Sistema de Arquivos (root) |
4>U-Boot com o kernel na flash e o sistema de arquivos remoto
Para essa opção, execute o script bootloader/scripts/uboot-nand-nfs.tcl pelo SAM-BA. O layout da nand flash será o seguinte:
| Endereço | Conteúdo |
| 0x00000000 | Bootloader |
| 0x00020000 | U-Boot |
| 0x00080000 | U-Boot Environment |
| 0x000A0000 | Kernel |
U-Boot com o kernel e o sistema de arquivos remotos
Para essa opção, execute o script bootloader/scripts/uboot-nfs-nfs.tcl pelo SAM-BA. Essa opção é particularmente interessante para testar modificações no kernel. O layout da nand flash será o seguinte:
| Endereço | Conteúdo |
| 0x00000000 | Bootloader |
| 0x00020000 | U-Boot |
| 0x00080000 | U-Boot Environment |
Kernel Loader sem U-Boot
O U-Boot é realmente uma ferramenta muito interessante, customizável e flexível, mas ainda temos a opção de carregar o kernel a partir da flash usando o programa de inicialização. Para isso vamos ter de fazer uma pequena alteração no programa de inicialização, por causa do endereço de carregamento e, principalmente, da quantidade de dados que serão lidos da flash para a RAM. Também é importante ter uma forma de passar parâmetros para o kernel, o que complica um pouco.
Parametros para o kernel
Existe um formato específico para a passagem de parâmetros de inicialização para o kernel através de tags e estruturas de dados binários. Entre as 10 tags existentes até esse momento, a mais interessante é a que passa a linha de comando. Entretanto, para garantir a integridade dos parâmetros, as tags que marcam o início e o fim dos parâmetros são obrigatórias. Em http://www.arm.linux.org.uk/developer/ pode-se encontrar um documento que descreve as tags. O kernel também é uma boa fonte de informações para estudos.
Um programa para formatação dos parâmetros
A ferramenta que grava dados na placa é o SAM-BA, que é capaz de executar scripts TCL. Em teoria seria possível fazer um script TCL para gerar os parâmetros em formato correto, mas como meus conhecimentos de TCL são nulos e meu foco não é aprender TCL nesse momento, construí um pequeno programa em C que recebe parâmetros pela linha de comando e gera um arquivo binário contendo os parâmetros no formato esperado pelo kernel.
Layout da flash
Para boot na NAND flash usando um sistema de arquivos também na flash, o layout será o seguinte:
| Endereço | Conteúdo |
| 0x00000000 | Bootloader |
| 0x00020000 | Kernel |
| 0x00220000 | Parâmetros |
| 0x00400000 | Sistema de Arquivos (root) |
Para gravar essa estrutura na flash, use o script bootloader/scritps/direct_nand_nand.tcl .
Para boot na NAND flash usando um sistema de arquivos na NFS, o layout será o seguinte:
| Endereço | Conteúdo |
| 0x00000000 | Bootloader |
| 0x00020000 | Kernel |
| 0x00220000 | Parâmetros |
Para gravar essa estrutura na flash, use o script bootloader/scritps/direct_nand_nfs.tcl .
Debug
Mensagens de debug nessa placa normalmente são enviadas pela porta DBGU. Para ativar o envio de mensagens pelo bootloader para a porta serial, defina a variável DEBUG=1 no script bootloader/1-bootstrap.sh.
Boot usando NFS
Para montar o sistema de arquivos usando NFS, defina as variáveis SERVERIP e DEVICEIP para os endereços IP do servidor (onde está o root do sistema de arquivos) e o endereço IP (fixo) do dispositivo. O script também cria um exemplo do arquivo de exportação de mountpoints no diretório build/tmp. Se usado como está, o endereço IP do servidor está definido como 192.168.20.1 e o do device é 192.168.20.100.
Melhorias
O boot demora menos de 20 segundos e, durante esse intervalo, nenhuma informação de progresso é mostrada para o usuário. Uma melhoria cosmética seria mostrar algo no display durante o boot.
Programas
| 01-alsa-utils.sh | Utilitários ALSA |
| 02-udev.sh | Gerenciador de Dispositivos |
| 03-bluez.sh | Suporte para Bluetooth |
| 04-bluez-tools.sh | * Ferramentas de apoio para bluetooth |
| 05-fscam.sh | Captura Frames de Webcam |
| 06-links.sh | Browser gráfico simples |
| 07-strace.sh | * Utilitário strace |
| 09-wirelesstools.sh | * Ferramentas para wi-fi |
| 10-wpa_supplicant.sh | Suporte para Wi-Fi |
| 12-fonts.sh | Fontes genéricas |
| 13-qingy.sh | Programa de Logon gráfico |
Os programas marcados com * teoricamente só são úteis durante o desenvolvimento.
Configurações
Configure suas redes Wi-Fi no arquivo app/files/wpa_list. O formato é simples: para cada linha, um nome de rede seguido pela senha, separados por '|' (pipe).
Configure os usuários pré-definidos no arquivo root/files/userlist.txt, cada usuário deve aparecer em uma linha com 3 campos separados por espaços, contendo pelo menos os 2 primeiros campos: NOME SENHA OUTROSDADOS
Bugs
Muitos. Os que eu achei:
- O driver ALSA de vez em quando não inicializa corretamente.
- O touchscreen precisa ser calibrado usando o programa ts_calibrate, copiei o arquivo de calibração gerado para minha placa de testes.
- O telnetd caiu algumas vezes sem motivo aparente.
Funciona/Não Funciona
| U-Boot | Bootloader | |
| Boot Direto | Bootloader | |
| NAND Flash | Hardware | |
| USB | Hardware | |
| Ethernet | Hardware | |
| Touch Screen | Hardware | |
| RTC | Hardware | |
| Botões Alternativos | Hardware | |
| Sleep | OS | |
| Frame Buffer | OS | |
| Câmera USB (Webcam) | OS | |
| Wi-Fi | OS | |
| USB Flash Drive | OS | |
| Teclado USB | OS | |
| Mouse USB | OS | |
| Som ALSA | Hardware | |
| USB Device | Hardware | |
| CAN | Hardware |
Instalação
Veja instruções para obter os scripts no SourceForge, usando SVN.
Cruze os dedos e execute o script "armat91/all.sh" para fazer o download, compilar e instalar todos os programas, bibliotecas e acessórios necessários. O resultado dos scripts será colocado no arquivo armat91/buildlog.txt.
Divirta-se!
Atualizado com informações para obter os scripts via SourceForge.net.





















