Em meados de 2010, conversava com meu amigo Giancarlo, sobre alguns inventos com eletrônica. Na ocasião conversávamos sobre um projetinho usando arduíno. A idéia era construir um timer eletrônico programável via internet, para ligar computadores remotamente. Ainda tínhamos nossas linhas telefônicas que conectavam em provedores que remuneravam pelas conexões (Crescenet, Orolix e Ganha). Enfim, o ultimo provedor fechou as portas, e ficamos a ver navios. Para eu que estava em Curitiba ainda restava o provedor Inteligweb. Então coloquei minha unica linha telefonica do apartamento para conectar. Nisto, conversando com ele sobre os inventos, ele apresentou o FriendlyARM Mini2440, onde eu poderia colocar ele para conectar a linha telefônica, sem precisar manter um computador somente para isto. Achei a ideia interessante, pois se trata de uma plataforma de desenvolvimento, então seria um aprendizado muito bom, sobre o funcionamento de sistemas embarcados.
Depois de revirar a internet, consegui entender como é feito a instalação do linux dentro do mini2440. Grande parte deste material só foi possível graças ao ótimo site do Sergio Prado, onde encontrei a maioria das respostas para algumas dúvidas. Aqui no site vou mostrar os passos para a instalação do sistema dentro do mini2440. Não explicarei toda a teoria do que foi implementado, sugiro acessarem o site dele para saberem maiores detalhes.
A idéia inicial é instalar o sistema operacional Emdebian, que é derivado do Debian, com os módulos de PPP e do adaptador serial Pl2303 habilitados no kernel. Parece simples, mas até chegar neste resultado, tive que garimpar bastante na internet, e por isso estou reproduzindo o que foi feito.
Como o mini2440 é baseado em uma arquitetura ARM, para compilar o kernel para rodar no mesmo, temos que montar uma plataforma de CROSS COMPILE. Cross Compile é a nomenclatura utilizada por um compilador que gera binários para rodar em plataformas diferentes. Vamos implementar um Cross em uma maquina de arquitetura i386, para gerar software para rodar em ARM.
Criaremos uma área que será utilizada para trabalhar com o mini2440
desenv:# adduser mini2440 desenv:# cd /home/mini2440/ desenv:# mkdir kernel ; cd kernel desenv:# git clone git://repo.or.cz/linux-2.6/mini2440.git desenv:# cd mini2440 desenv:# mkdir -p ../kernel-bin
Vamos instalar os pacotes de build necessários para a compilação
desenv:# apt-get install libncurses5-dev build-essential
Também é necessário alguns toolchains que irão auxiliar no processo de compilação
desenv:# wget http://www.codesourcery.com/sgpp/lite/arm/portal/package4571/public/arm-none-linux-gnueabi/arm-2009q1-203-arm-none-linux-gnueabi-i686-pc-linux-gnu.tar.bz2 desenv:# tar -jxf arm-2009q1-203-arm-none-linux-gnueabi-i686-pc-linux-gnu.tar.bz2 desenv:# export PATH=$PATH:/home/mini2440/arm-2009q1/bin
Para enviar a imagem do kernel para o ARM, usaremos um servidor TFTP. Trabalharemos em cima do Emdebian na máquina de desenvolvimento, que será carregado no mini2440 via NFS. Também realizaremos a instalação do u-boot, que é um sisteminha de bootloader do arm, que poderá ser enviado ao ARM via USB.
A seguir vamos instalar os servidores necessários na nossa maquina de desenvolvimento.
Servidor NFS
desenv:# apt-get install nfs-kernel-server portmap desenv:# echo -e "\n/home/mini2440/rootfs 192.168.0.171(rw,no_root_squash,sync)\n" >> /etc/exports desenv:# /etc/init.d/portmap restart desenv:# /etc/init.d/nfs-kernel-server restart
A pasta rootfs é onde ficará a pasta raiz do emdebian, e o ip 192.168.0.171 é o ip que será atrelado ao ARM
Servidor TFTP
desenv:# apt-get install atftpd desenv:# mkdir /tftpboot desenv:# chmod -R 777 /tftpboot desenv:# chown -R nobody /tftpboot desenv:# /etc/init.d/atftpd restart
Depois de gerada a imagem do kernel, será enviada para a pasta raiz do tftp para enviar ao ARM. Agora com a nossa maquina ajustada, vamos iniciar o processo de compilação do u-boot e do kernel. Dentro da pasta que criamos para o ambiente de compilação, vamos baixar o fonte do u-boot e compilar tudo.
desenv:# mkdir uboot ; cd uboot desenv:# git clone git://repo.or.cz/u-boot-openmoko/mini2440.git desenv:# export CROSS_COMPILE=arm-none-linux-gnueabi- desenv:# cd mini2440 desenv:# make mini2440_config
Se ocorreu tudo bem, por enquanto vamos deixar o u-boot de lado, e deixar para enviar para o ARM depois. Agora vamos trabalhar com o kernel.
desenv:# cd ../.. desenv:# CROSS_COMPILE=arm-none-linux-gnueabi- ARCH=arm make O=../kernel-bin/ mini2440_defconfig desenv:# cd ../kernel-bin desenv:# make ARCH=arm menuconfig
Selecionaremos alguns módulos que deverão ser compilados junto com o kernel
Device Drivers ---> [*] Network device support ---> [M] PPP (point-to-point protocol) support [*] PPP multilink support (EXPERIMENTAL) [*] PPP filtering [M] PPP support for async serial ports [M] PPP support for sync tty ports [M] PPP Deflate compression [M] PPP BSD-Compress compression [M] PPP MPPE compression (encryption) (EXPERIMENTAL) [M] PPP over Ethernet (EXPERIMENTAL) [M] PPP over L2TP (EXPERIMENTAL) [*] USB support ---> [M] USB Serial Converter support ---> [M] USB Prolific 2303 Single Port Serial Driver
Agora todos me perguntam. Por que o modulo PPP e o conversor serial ? Bom, a idéia é usar este conversor usb-serial para conectar a um hardmodem US Robotics, que será o responsável pela nossa conexão dial-up, para conectar no provedor Inteligweb, e me gerar uns trocados $$$. O conversor serial tornou-se necessário, pois a porta DB9 do ARM é de uso exclusivo do console, para o gerenciamento do boot do sistema.
Agora, é só compilar o kernel.
desenv:# cd ../mini2440 desenv:# CROSS_COMPILE=arm-none-linux-gnueabi- ARCH=arm make O=../kernel-bin/
Caso seja necessário compilar somente módulos dinâmicos, o mesmo poderá ser feito da seguinte maneira
desenv:# cd ../mini2440 desenv:# CROSS_COMPILE=arm-none-linux-gnueabi- ARCH=arm make O=../kernel-bin/ modules desenv:# CROSS_COMPILE=arm-none-linux-gnueabi- ARCH=arm make O=../kernel-bin/ INSTALL_MOD_PATH=.. modules_install
Depois de compilado o kernel, vamos gerar uma imagem do kernel, que será enviado para o mini2440 via tftp.
desenv:# cd uboot/mini2440/tools/ desenv:# ./mkimage -A arm -O linux -T kernel -C none -a 0x30008000 -e 0x30008000 -d ../../../kernel/kernel-bin/arch/arm/boot/zImage /tftpboot/uImage
O resultado da geração da imagem será parecido com isto:
Image Name: Created: Sat Jan 15 15:08:15 2011 Image Type: ARM Linux Kernel Image (uncompressed) Data Size: 2045640 Bytes = 1997.70 kB = 1.95 MB Load Address: 30008000 Entry Point: 30008000
Anote o Data Size, pois será utilizado quando enviarmos o kernel lá para o arm.
Agora que já temos o U-boot e o kernel compilado, é hora de enviar para o ARM. Para acessar o ARM, deveremos conectar um cabo serial entre as duas máquinas, e utilizar o pipocom para acessar a console.
desenv:# apt-get install picocom desenv:# picocom -b 115200 /dev/ttyS0 --send-cmd "sx -vv"
Inicie o ARM com a chave NOR, para ter acesso ao menu do supervivi
[q] Goto shell of vivi Enter your selection: q Supervivi> load ram 0x31000000 242360 u
No primeiro momento, vamos carregar o u-boot para a memoria RAM do mini2440, para depois salvar na memoria flash. O 0×31000000 é o endereço de memória da RAM, e o 242360 é o tamanho em bits da imagem do U-boot. Ao pressionar o enter, o ARM vai aguardar a imagem ser enviada pela interface USB. Na maquina de desenvolvimento, fazemos o upload desta imagem com o usbpush.
desenv:# ./usbpush uboot/mini2440/u-boot.bin
Finalizado o envio, voltamos para a console do ARM.
Supervivi> go 0x31000000
Com este comando, a gente executa o U-boot diretamente na memoria RAM, sendo possivel assim, formatar a NAND flash, para receber o kernel e o Emdebian.
Supervivi > go 0x31000000 MINI2440 # nand scrub Really scrub this NAND flash? y/N MINI2440 # nand createbbt MINI2440 # saveenv MINI2440 # dynenv set 40000 MINI2440 # setenv ipaddr 192.168.0.171 MINI2440 # setenv serverip 192.168.0.170 MINI2440 # saveenv
Os parâmetros ipaddr e serverip são respectivamente, o ip que será utilizado no ARM, e o ip do servidor NFS, que no nosso caso, é a nossa maquina de desenvolvimento. Depois de configurado, basta salvar tudo na memória flash.
MINI2440 # nand write.e 0x31000000 0 242360
Só relembrando, o numero 242360 é o tamanho em bits da imagem do U-boot. Depois disto, podemos desligar a chave NOR, resetar, e realizar o boot diretamente no U-boot. Com o U-boot instalado, podemos puxar a imagem do kernel para o mini2440, e salvar na flash.
MINI2440 # tftp 0x31000000 uImage MINI2440 # nand erase kernel MINI2440 # nand write.e 0x31000000 kernel
O 1f3708 é o tamanho da imagem do kernel, em hexadecimal. Já que estamos na console do ARM, já vamos deixar configurado, os parâmetros do boot via NFS, para buscar o Emdebian no nosso pc de desenvolvimento.
MINI2440 # setenv bootargs console=ttySAC0,115200 noinitrd init=/sbin/init rw mini2440=0tb ip=192.168.0.171 root=/dev/nfs rw nfsroot=192.168.0.170:/home/mini2440/rootfs MINI2440 # setenv bootcmd 'nboot.e kernel ; bootm'
No nosso ARM, já está tudo pronto para o primeiro boot. Agora vamos voltar a nossa maquina de desenvolvimento, para mexer com o Emdebian.
desenv:# cd /home/mini2440/rootfs desenv:# wget http://mini2440.googlecode.com/files/emdebian-grip-090306-armel-lenny-installed.tar.bz2 desenv:# tar -xvjf emdebian-grip-090306-armel-lenny-installed.tar.bz2
Fácil né ?…Assim já podemos realizar o primeiro boot do emdebian. Para o funcionamento básico, até aqui já é suficiente. Mas vamos adiante, pois queremos configurar o emdebian, e ainda salvar a imagem do mesmo na flash do ARM, sem necessitar de um computador para bootar o emdebian.
Instalando o Emdebian na Nand
Durante o estudo, cheguei a conclusão que a maioria das referencias, sugeriam via u-boot, realizar o tftp da imagem do SO para a memória RAM, e daí sim salvar na nand flash. Bom, como o meu ARM tem 64 MB, então nenhuma imagem poderia ultrapassar este valor. Ao baixar o emdebian vi que o mesmo excedia o tamanho de 64 MB, entao busquei insistentemente por uma solução. Com o emdebian carregando via NFS, temos mais ferramentas para conseguir trabalhar com a formatação da Flash, e sim instalar o sistema operacional.
mini2440:# apt-get install mtd-utils bzip2 mini2440:# flash_eraseall -j /dev/mtd3 mini2440:# mount -t jffs2 /dev/mtdblock3 /mnt/ mini2440:# cd /mnt/ mini2440:# wget http://mini2440.googlecode.com/files/emdebian-grip-090306-armel-lenny-installed.tar.bz2 mini2440:# tar -jxf emdebian-grip-090306-armel-lenny-installed.tar.bz2 mini2440:# umount /mnt/ mini2440:# reboot
Vamos instalar no ARM, o mtd-utils, que nos dará ferramentas para manipulação de memórias flash, e o bzip2, para conseguir descompactar a imagem do emdebian. Depois disto vamos formatar o /dev/mtd3, que corresponde a partição de rootfs definida por default pelo u-boot. Na dúvida, rode o comando cat /proc/mtd no ARM, trazendo informações sobre a memória flash que está instalada no ARM.
Após concluir a formatação, fazemos a montagem da partição da memória flash, que já está em formato jffs2, para dai sim jogar o emdebian lá dentro. Vejamos, pode parecer estranho, mas formatamos o /dev/mtd3 e montamos o /dev/mtdblock3, não estaria errado ?
Não está errado, como sou muito ruim em explicação, vou tentar deixar uma idéia do que é isto. Uma das fontes pesquisadas diz o seguinte:
When using Linux, interaction with the Flash device is controlled through the MTD subsystem. The MTD subsystem exports two device nodes per Flash partition. These are:
- /dev/mtd# – A Character device that is used to access the raw flash device.
- /dev/mtdblock# – A block device used to access the disk/block established in the raw flash.
In the above device nodes the ‘#’ sign represents the partition number. For example partition 0 would have the device nodes /dev/mtd0 and /dev/mtdblock0
Depois disto, acessamos o ponto de montagem, em /mnt, fazemos o download do emdebian (de novo), descompactamos, desmontamos a partição, e reboot. Está quase pronto…com o reboot, entramos no console do u-boot para setar os parâmetros para bootar via memória flash.
MINI2440 # setenv bootargs 'root=/dev/mtdblock3 rw rootfstype=jffs2 noinitrd console=ttySAC0,115200' MINI2440 # setenv bootcmd 'nboot.e kernel ; bootm' MINI2440 # saveenv MINI2440 # boot
Pronto !!…Desta maneira, o emdebian estará instalado no ARM, e não será mais necessário o uso do servidor NFS para carregar o sistema operacional.
A partir daqui, cada um pode personalizar o seu mini2440 da maneira que bem entender. Vale lembrar, que os módulos dinâmicos do kernel, que foram eventualmente compilados, deverão ser copiados para o ARM. Para que isto seja possivel, instale o ssh-server, e envie os módulos para a pasta /lib/modules
Um forte abraço
Fontes de pesquisa
http://processors.wiki.ti.com/index.php/Put_JFFS2_Image_to_Flash
http://www.sergioprado.org/2010/08/30/mini2440-linux-com-u-boot-e-emdebian/


Olá Jeferson,
Parabéns pelo ótimo post! Gostei da solução de usar o NFS montado para escrever na flash. Nem tinha pensado nisso… Vivendo e aprendendo!
Um abraço!
Valeu Sergio
Bati muita cabeça, mas valeu a pena…hehe
Abraço
Legal, Jeferson, não sabia que trabalhava com hardware. Cheguei aqui pelos blogs de investimentos.
Obrigado Fabio
Na verdade esta foi minha primeira experiência com hardware deste tipo, sou apenas um principiante…hehe.
Abraço
Prezado amigo:
Quando, depois de compilar o Kernel, na etapa:
# desenv:# cd uboot/mini2440/tools/
# desenv:# ./mkimage -A arm -O linux -T kernel -C none -a 0×30008000 -e 0×30008000 -d ../../../kernel/kernel-bin/arch/arm/boot/zImage /tftpboot/uImage
Na verdade é cd /home/mini2440/uboot/mini2440/tools, certo?
O problema é que o mkimage não foi gerado (não há o executável, apenas o fonte, em c).
Alguma ideia? Obrigado.
Outra pergunta:
Preciso gerar o sistema de arquivos com o kernel, para rodar programa com Qt4 e ncurses.
Você sabe me dizer aonde posso encontrar um local com tutoriais sobre isto?
tentei usar o buildroot, mas as imagens que gerei não funcionaram (tanto do kernel quanto do filesystem).
Obrigado
Olá Jeferson,
Também quer parabenizá-lo pelo post. Foi de muita ajuda, pois tenho um mini2440 com 64MB. A diferença é que não tive que procurar muito por uma solução para carregar o emdebian, graças a você.
Abraços
Hehehe…Valeu cara. E olha que eu apanhei um monte para fazer o que eu queria, mas deu certo, e está funcionando perfeitamente…