Linux e o suporte à device tree – Parte 3
- por Sergio Prado
Na parte 1 desta série de artigos escrevi sobre a necessidade de um mecanismo para identificar a topologia de hardware do sistema, e na parte 2 vimos como o device tree procura resolver este problema.
Neste artigo iremos colocar a mão na massa e carregar o Linux através de um device tree. Faremos os testes na Beagleboard-xM e no i.MX53 QSB.
DEVICE TREE NA BEAGLEBOARD-XM
Para realizar os testes, você vai precisar de um toolchain instalado na sua máquina e de um sistema Linux rodando na Beagleboard-xM.
O primeiro passo é compilar uma versão do U-Boot com suporte ao device tree. Para isso, baixe a última versão do U-Boot do site do projeto (eu usei a versão 2013.01) e compile-o para a Beagleboard-xM (altere a variável CROSS_COMPILE de acordo com o seu toolchain):
$ make CROSS_COMPILE=arm-linux-gnueabi- omap3_beagle_config $ make CROSS_COMPILE=arm-linux-gnueabi- |
Copie os arquivos MLO e u-boot.img para a partição de boot do cartão SD.
Baixe a última versão do Linux em http://kernel.org (eu testei com a versão 3.8.3) e compile-o para a Beagleboard-xM (altere a variável CROSS_COMPILE de acordo com o seu toolchain):
$ make ARCH=arm omap2plus_defconfig $ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- uImage |
Ainda no diretório do Linux, gere o DTB (altere a variável CROSS_COMPILE de acordo com o seu toolchain):
$ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- omap3-beagle-xm.dtb |
Copie os arquivos uImage e omap3-beagle-xm.dtb para a partição de boot do cartão SD.
Ainda na partição de boot do cartão SD, crie o arquivo uEnv.txt e adicione as linhas abaixo:
mmcrootfstype=ext2 rootwait fdtaddr=0x81000000 loaduimage=fatload mmc 0 ${loadaddr} uImage; fatload mmc 0 ${fdtaddr} omap3-beagle-xm.dtb; fdt addr ${fdtaddr}; mmcboot=echo Booting from mmc ...; run mmcargs; bootm ${loadaddr} - ${fdtaddr} |
Este arquivo possibilita a configuração das variáveis de ambiente do U-Boot. É nesse arquivo então que definimos algumas variáveis que definem o comportamento do U-Boot no boot da placa.
Uma variável importante é a loaduimage. Ela é executada no boot, fazendo a carga do device tree para a memória no endereço 0x81000000 com o comando fatload. E na variável mmcboot, que também é executada no boot da placa, instruímos o U-Boot para avisar o kernel da presença do device tree no endereço 0x81000000 com o comando bootm. O U-boot faz isso configurando o endereço do device tree em um registrador da CPU, que o kernel irá ler no boot do equipamento.
Agora é só testar. Coloque o cartão na Beagleboard-xM e ligue-a. Se tudo der certo, você terá acesso ao device tree no /proc:
# ls /proc/device-tree/ #address-cells compatible memory soc #size-cells cpus model sound aliases interrupt-parent name chosen leds ocp |
DEVICE TREE NO I.MX53 QSB
Para realizar os testes, você vai precisar de um toolchain instalado na sua máquina e de um sistema Linux rodando no i.MX53 QSB.
O primeiro passo também é compilar uma versão do U-Boot com suporte ao device tree. Para isso, baixe a última versão do U-Boot do site do projeto (eu usei a versão 2013.01) e compile-o para o i.MX53 QSB (altere a variável CROSS_COMPILE de acordo com o seu toolchain):
$ make CROSS_COMPILE=arm-linux-gnueabi- mx53loco_config $ make CROSS_COMPILE=arm-linux-gnueabi- |
Grave o bootloader no cartão SD (substitua <device> pelo nome do arquivo de dispositivo do cartão SD):
$ sudo dd if=u-boot.imx of=/dev/<device> seek=2 oflag=dsync |
Baixe a última versão do Linux em http://kernel.org (eu testei com a versão 3.8.3) e compile-o para o i.MX53 (altere a variável CROSS_COMPILE de acordo com o seu toolchain):
$ make ARCH=arm mrproper $ make ARCH=arm imx_v6_v7_defconfig |
Antes de compilar, abra o menu de configuração:
$ make ARCH=arm menuconfig |
E habilite a opção CONFIG_PROC_DEVICETREE:
Device Drivers -> Device Tree and Open Firmware support -> [*] Support for device tree in /proc |
Salve e feche. Agora compile o kernel (altere a variável CROSS_COMPILE de acordo com o seu toolchain):
$ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- LOADADDR=0x70008000 uImage |
Ainda no diretório do Linux, gere o DTB (altere a variável CROSS_COMPILE de acordo com o seu toolchain):
$ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- imx53-qsb.dtb |
Agora grave o kernel e o DTB no cartão SD (substitua <device> pelo nome do arquivo de dispositivo do cartão SD):
$ sudo dd if=arch/arm/boot/uImage of=/dev/<device> seek=2048 oflag=dsync $ sudo dd if=arch/arm/boot/dts/imx53-qsb.dtb of=/dev/<device> seek=10240 oflag=dsync |
Acesse o prompt do U-Boot e configure os parâmetros bootcmd e bootargs:
> setenv bootcmd 'mmc read ${loadaddr} 0x800 0x2000; mmc read ${fdt_addr} 0x2800 0x100; bootm ${loadaddr} - ${fdt_addr}' > setenv bootargs console=ttymxc0,${baudrate} root=/dev/mmcblk0p1 rootfstype=ext2 > saveenv |
Aqui o bootcmd faz a mágica de ler o device tree do cartão SD e carregá-lo para a memória, iniciando depois o kernel com o comando bootm.
Reinicie e teste. Se tudo der certo, você terá acesso ao device tree no /proc:
# ls /proc/device-tree/ #address-cells memory #size-cells model aliases name chosen regulators clocks soc compatible sound gpio-keys tz-interrupt-controller@0fffc000 leds |
DOIS EM UM?
O próximo passo seria ter uma única imagem do kernel (uImage) que funcione nos dois kits de desenvolvimento, afinal esta é uma das promessas do device tree!
Para isso, você pode habilitar a opção “Allow multiple platforms to be selected” na configuração do kernel em “System Type -> ARM system type“.
Veja na imagem acima que já é possível ter uma única imagem do kernel com suporte à diferentes SoCs, como os da Marvell, Broadcom, Freescale i.MX e Allwinner A1X (clique na imagem para expandi-la).
Mas infelizmente este suporte ainda não esta pronto na versão 3.8.3 do kernel para a linha OMAP da Texas, por isso não conseguiremos criar uma única imagem que funcione ao mesmo tempo no i.MX53 QSB e na Beagleboard-xM! :(
Assim que este suporte estiver pronto, farei os testes e publicarei os resultados aqui no blog.
Um abraço!
Sergio Prado