Comunicação entre núcleos assimétricos com o i.MX6SoloX da Freescale

- por Sergio Prado

Categorias: Linux Tags: , ,

Lançado em fevereiro na Embedded World 2015, o i.MX6SoloX da Freescale é o primeiro SoC (System on Chip) do mercado com os núcleos ARM Cortex-A9 e Cortex-M4. Devido à sua arquitetura assimétrica, este chip permite executar sistemas operacionais diferentes em cada núcleo, de forma independente.

Por exemplo, podemos ter o kernel Linux rodando no Cortex-A9 e gerenciando a comunicação e a interface com o usuário, e no Cortex-M4 podemos colocar um RTOS (FreeRTOS, MQX, etc) para tratar eventos de tempo real da aplicação. Tudo isso no mesmo SoC!

Além dos núcleos de processamento, o i.MX6SoloX possui uma GPU 2D/3D Vivante para processamento gráfico, suporte para câmera e display, além de diversas interfaces de comunicação e controle como ethernet, PCIe, USB, I2C, I2S, etc.

imx6solox

Eu fui um dos felizardos a receber em primeira mão da Freescale uma placa com o i.MX6SoloX para testar a comunicação entre os núcleos do SoC. Esta placa é a SABRE Board for Smart Devices Based on the i.MX 6SoloX.

Ela é bem completa, e além do i.MX6SoloX, possui 1G de RAM, 64MB de flash NOR, três interfaces de cartão SD, saída para display RGB e LVDS, câmera, entrada e saída de áudio, portas USB host e OTG, ethernet gigabit, CAN, PCIe, conversores A/D e sensores (acelerômetro, compasso e luz ambiente).

Uma das portas USB possui um chip da FTDI que, quando conectada ao host, cria automaticamente duas portas seriais, uma para acessar a console do Linux rodando no Cortex-A9 e outra para acessar a console do firmware rodando no Cortex-M4.

sabre

O objetivo deste artigo é descrever os passos necessários para compilar e testar uma aplicação de demonstração da Freescale para a comunicação entre os dois núcleos de processamento.

Rodaremos o Linux no Cortex-A9 e o MQX no Cortex-M4. Os dois kernels se comunicarão através de uma região de memória compartilhada utilizando a biblioteca MCC (MultiCore Communication) da Freescale.

Para realizar este trabalho, consultei o BSP (Board Support Package) liberado pela Freescale para esta plataforma. Tive problemas na execução de alguns passos específicos, mas consegui solucionar consultando o fórum do i.MX Community.

PREPARANDO O AMBIENTE

Todos os testes foram realizados em uma máquina com o sistema operacional Ubuntu 14.04 64 bits.

O primeiro passo é instalar na máquina de desenvolvimento as ferramentas que utilizaremos para compilar a distribuição Linux e testar a aplicação:

$ sudo apt-get install gawk wget git-core diffstat unzip texinfo gcc-multilib build-essential chrpath socat libsdl1.2-dev xterm picocom

Instale também a ferramenta repo, que será utilizada para baixar o código-fonte do BSP da Freescale (baseado no Yocto Project):

$ mkdir ~/bin
$ curl http://commondatastorage.googleapis.com/git-repo-downloads/repo > ~/bin/repo
$ chmod a+x ~/bin/repo
$ export PATH=${PATH}:~/bin

Crie uma variável de ambiente para armazenar o nome do diretório que utilizaremos para compilar o firmware do MQX e a distribuição Linux (não se esqueça de recriar esta variável caso encerre o terminal corrente ou abra um novo terminal):

$ export IMX6SOLOX=~/imx6solox
$ mkdir -p $IMX6SOLOX

DISTRIBUIÇÃO LINUX

Vamos primeiro colocar o Linux para rodar no Cortex-A9.

O boot do sistema é realizado por uma das interfaces de cartão SD da placa. É possível gravar uma imagem pré-compilada distribuída junto com o BSP ou compilar uma imagem usando as ferramentas do Yocto Project. Neste tutorial vamos optar pela segunda opção.

Crie um diretório e baixe o código-fonte da camadas de BSP da Freescale:

$ cd $IMX6SOLOX
$ mkdir -p fsl-release-bsp && cd fsl-release-bsp
$ repo init -u git://git.freescale.com/imx/fsl-arm-yocto-bsp.git -b imx-3.10.53-1.1.0_ga
$ repo sync

Agora compile a distribuição Linux com os comandos abaixo:

$ MACHINE=imx6sxsabresd source fsl-setup-release.sh -b build
$ bitbake core-image-minimal

A compilação pode levar algumas horas, dependendo da capacidade da sua máquina de desenvolvimento. Ao final, as imagens estarão disponíveis no diretório abaixo:

$ cd tmp/deploy/images/imx6sxsabresd/
$ ls
core-image-minimal-imx6sxsabresd-20150331171304.rootfs.ext3      zImage--3.10.53-r0-imx6sx-sdb-emmc-20150331171304.dtb
core-image-minimal-imx6sxsabresd-20150331171304.rootfs.manifest  zImage--3.10.53-r0-imx6sx-sdb-lcdif1-20150331171304.dtb
core-image-minimal-imx6sxsabresd-20150331171304.rootfs.sdcard    zImage--3.10.53-r0-imx6sx-sdb-ldo-20150331171304.dtb
core-image-minimal-imx6sxsabresd-20150331171304.rootfs.tar.bz2   zImage--3.10.53-r0-imx6sx-sdb-m4-20150331171304.dtb
core-image-minimal-imx6sxsabresd.ext3                            zImage--3.10.53-r0-imx6sx-sdb-reva-20150331171304.dtb
core-image-minimal-imx6sxsabresd.manifest                        zImage--3.10.53-r0-imx6sx-sdb-reva-ldo-20150331171304.dtb
core-image-minimal-imx6sxsabresd.sdcard                          zImage--3.10.53-r0-imx6sx-sdb-sai-20150331171304.dtb
core-image-minimal-imx6sxsabresd.tar.bz2                         zImage-imx6sxsabresd.bin
modules--3.10.53-r0-imx6sxsabresd-20150331171304.tgz             zImage-imx6sx-sdb.dtb
modules-imx6sxsabresd.tgz                                        zImage-imx6sx-sdb-emmc.dtb
README_-_DO_NOT_DELETE_FILES_IN_THIS_DIRECTORY.txt               zImage-imx6sx-sdb-lcdif1.dtb
u-boot.imx                                                       zImage-imx6sx-sdb-ldo.dtb
u-boot-imx6sxsabresd-2014.04-r0.imx                              zImage-imx6sx-sdb-m4.dtb
u-boot-imx6sxsabresd.imx                                         zImage-imx6sx-sdb-reva.dtb
zImage                                                           zImage-imx6sx-sdb-reva-ldo.dtb
zImage--3.10.53-r0-imx6sxsabresd-20150331171304.bin              zImage-imx6sx-sdb-sai.dtb
zImage--3.10.53-r0-imx6sx-sdb-20150331171304.dtb

Grave a imagem com extensão .sdcard no cartão SD (sub­sti­tua /dev/sdX no comando abaixo pelo nome do arquivo de dis­pos­i­tivo do cartão SD):

$ sudo dd if=core-image-minimal-imx6sxsabresd.sdcard of=/dev/sdX bs=1M && sync

Para testar, coloque o cartão SD na interface SD4 da placa e conecte sua máquina de desenvolvimento ao target com um cabo USB no conector J16 da placa.

Utilize sua aplicação de terminal preferida para testar o boot do Linux. Para logar, o usuário é root e não precisa de senha.

Booting Linux on physical CPU 0x0
Linux version 3.10.53-1.1.0_ga+g496fbe0b831b (sprado@sprado-desktop) (gcc version 4.8.2 (GCC) ) #1 SMP PREEMPT Tue Mar 31 14:47:46 BRT 2015
CPU: ARMv7 Processor [412fc09a] revision 10 (ARMv7), cr=10c53c7d
CPU: PIPT / VIPT nonaliasing data cache, VIPT aliasing instruction cache
Machine: Freescale i.MX6 SoloX (Device Tree), model: Freescale i.MX6 SoloX SDB Board
[...]
 
Poky (Yocto Project Reference Distro) 1.6.2 imx6sxsabresd /dev/ttymxc0
 
imx6sxsabresd login:

FIRMWARE MQX

No Cortex-M4 rodaremos uma aplicação baseada no MQX, o sistema operacional de tempo real da Freescale.

O primeiro passo é baixar a última versão do código-fonte do MQX para o i.MX6SoloX do site da Freescale. Nos meus testes, utilizei a versão 4.1.0. Não esqueça de baixar a versão para Linux (*.gz).

Crie um diretório e descompacte o código-fonte nele:

$ cd $IMX6SOLOX
$ mkdir -p mqx && cd mqx
$ tar xfv ~/Downloads/Freescale\ MQX\ RTOS\ 4.1.0\ for\ i.MX\ 6SoloX\ Linux\ Base.gz

Verifique se o código-fonte foi descompactado corretamente:

$ ls
build config doc mcc mqx tools

Antes de compilar o MQX, precisamos de um toolchain. Baixe o instale o toolchain com os comandos abaixo:

$ cd $IMX6SOLOX
$ mkdir -p toolchain && cd toolchain
$ wget https://launchpad.net/gcc-arm-embedded/4.8/4.8-2014-q1-update/+download/gcc-arm-none-eabi-4_8-2014q1-20140314-linux.tar.bz2
$ tar xfv gcc-arm-none-eabi-4_8-2014q1-20140314-linux.tar.bz2 && rm gcc-arm-none-eabi-4_8-2014q1-20140314-linux.tar.bz2

Agora retorne ao diretório do código-fonte do MQX e compile-o:

$ cd $IMX6SOLOX/mqx/build/imx6sx_sdb_m4/make
$ export TOOLCHAIN_ROOTDIR=$IMX6SOLOX/toolchain/gcc-arm-none-eabi-4_8-2014q1
$ ./build_gcc_arm.sh

Por fim, compile a aplicação de demonstração:

$ cd $IMX6SOLOX/mqx/mcc/examples/pingpong/build/make/pingpong_example_imx6sx_sdb_m4
$ ./build_gcc_arm.sh

A aplicação de demonstração é compilada no formato ELF. Converta-a para o formato binário:

$ arm-none-eabi-objcopy -O binary gcc_arm/extflash_release/pingpong_example_imx6sx_sdb_m4.elf m4_qspi.bin

O boot do Cortex-M4 pode ser realizado pela memória flash NOR da placa. Para gravar o firmware, a Freescale implementou um comando no U-Boot capaz de ler a imagem do firmware do cartão SD e gravar na flash NOR.

Portanto, insira novamente o cartão SD na máquina de desenvolvimento e copie o binário para a primeira partição do cartão (não esqueça de montar a primeira partição do cartão SD e alterar o diretório do ponto de montagem no comando abaixo):

$ cp m4_qspi.bin /media/sprado/Boot\ imx6sx/

Acesse a console do Linux, reinicie a placa e pressione uma tecla para acessar o prompt de comandos do U-Boot. Execute o comando abaixo para gravar o firmware na flash NOR da placa:

> run update_m4_from_sd

É também responsabilidade do U-Boot iniciar a execução do firmware no Cortex-M4 no boot. Para isso, configure os parâmetros de boot conforme abaixo:

> setenv fdt_file imx6sx-sdb-m4.dtb
> setenv mmcargs "${mmcargs} uart_from_osc"
> setenv bootcmd "run m4boot;${bootcmd}"
> saveenv

Agora abra um outro terminal para acessar a console do Cortex-M4 e reinicie a placa. Você deverá ver as mensagens abaixo:

***** MCC PINGPONG EXAMPLE *****
Please wait :
1) A9 peer is ready
Then press "S" to start the demo
********************************
 
Press "S" to start the demo :

Na console do Linux no target, faça o login e inicie a aplicação de teste da comunicação multicore:

# echo 1 > /sys/devices/soc0/soc.1/2200000.aips-bus/mcctest.17/pingpong_en &

Na console do MQX no Cortex-M4, pressione “S” para iniciar a comunicação com o Linux.

A partir deste momento, o Linux e o MQX, rodando de forma independente em cada núcleo, começarão a trocar mensagens utilizando uma região de memória compartilhada através da biblioteca MCC da Freescale.

O QUE VEM POR AÍ?

Com este tipo de arquitetura assimétrica, podemos juntar o melhor dos dois mundos: aplicações de processamento geral e sistemas de tempo real. E a tendência é que mais fabricantes de hardware optem por este tipo de arquitetura.

Ainda falta um padrão de software para que possamos desenvolver aplicações portáveis, mas conforme a quantidade de SoCs com esta capacidade aumente, a comunidade do kernel Linux deverá trabalhar em um framework genérico para comunicação entre núcleos assimétricos. É esperar para ver!

Um abraço,

Sergio Prado

Faça um Comentário

Navegue
Creative Commons Este trabalho de Sergio Prado é licenciado pelo
Creative Commons BY-NC-SA 3.0.