-
Notifications
You must be signed in to change notification settings - Fork 287
Dragonboard Hexagon DSP
This page will help you setting up your environment to execute code on the Hexagon DSP on a Dragonboard 410c.
- Linux based host machine.
- DragonBoard 410c running debian. You can get 96boards images here. The installation instructions are pretty straightforward and can be found here.
- The Linaro Toolchain.
- The Hexagon SDK.
- A Linux kernel tree with support for the adsprpc driver.
- You also need the apq8016 modem firmware files r1036.1 to get FastRPC support. These files are about to be released through the Qualcomm Developer Network. You'll need to replace the files /lib/firmware/modem.* in your stock rootfs with the r1036.1 ones.
For the purpose of this documentation, let's say your working directory is ~/dev.
To compile the Linux kernel and also the Hexagon sample applications you'll need the aarch64 Linaro toolchain. Download the archive named as gcc-linaro-x.y.z-201Y.MM-x86_64_aarch64-linux-gnu.tar.xz and decompress it into your ~/dev folder.
You need to install the Hexagon SDK to compile the sample application. The SDK can be downloaded here. Choose version 3.2 as the latest version 3.3 has trouble to compile the sample applications.
Once installed, you need a couple of extra steps to be able to compile the example.
In order to compile the sample applications using the standard Linux target you must add the Linaro toolchain to the Hexagon SDK.
This is usually done by copying the Linaro toolchain into the SDK tools sub-folder. Creating a symbolic link to the toolchain folder we've already setup is actually enough.
$ ln -s ~/dev/gcc-linaro-version-date-x86_64_aarch64-linux-gnu /PATH/TO/HEXAGON/SDK/tools/linaro
This step will select a qaic executable that fits your distribution.
$ cd /PATH/TO/HEXAGON/SDK/tools/qaic
$ make
This creates a "Linux" sub-folder containing the qaic executable.
A Linux kernel tree with FastRPC support is available here and can be cloned with the following commands:
$ cd ~/dev
$ git clone -b integration-linux-qcomlt https://git.linaro.org/landing-teams/working/qualcomm/kernel.git
$ export ARCH=arm64
$ export CROSS_COMPILE=~/dev/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-
$ cd ~/dev/kernel
$ make defconfig
$ make
You have to copy the modules to the DragonBoard root filesystem. Depending on how you're booting your device it might be easy or a bit more complex.
If the rootfs is located on the internal eMMC you have to install the modules somewhere on the host hard drive:
$ make INSTALL_MOD_PATH=~/dev modules_install
The developer image allows you to remotely connect to the DragonBoard through ssh (using the credentials linaro/linaro) and you can copy the modules to the DragonBoard using scp.
First you need to delete the source and build symlinks in the modules folder (otherwise scp will follow them and copy the build and source trees to the DragonBoard).
$ find ~/dev/lib/modules -type l -print -delete
It's now safe to copy the entire folder to the board rootfs:
$ scp -r ~/dev/lib/modules linaro@DB_IP_ADDR:~/dev
Then ssh to the DragonBoard and move the modules folder:
$ ssh linaro@DB_IP_ADDR
DB $ sudo mv ~/dev/modules/* /lib/modules
It is easier if you boot directly from the SD. Simply mount the SD card on your host system and install the modules directly to the SD card by passing the rootfs mount point.
$ make INSTALL_MOD_PATH=/PATH/TO/MOUNTED/ROOTFS/ modules_install
Now you need to build a boot image for the db410c and boot it using fastboot. You'll need a few more tools to build the boot image.
$ cd ~/dev
$ wget https://snapshots.linaro.org/96boards/dragonboard410c/linaro/debian/latest/initrd.img-4.14.0-qcomlt-arm64
$ git clone git://codeaurora.org/quic/kernel/skales
$ ~/dev/skales/dtbTool -o ~/images/dt.img -s 4096 ~/dev/kernel/arch/arm64/boot/dts/qcom/
$ export CMDLINE="root=/dev/disk/by-partlabel/rootfs rw rootwait console=tty0 console=ttyMSM0,115200n8"
In this example, the rootfs is located on the DragonBoard eMMC. If your rootfs is located on the SD card you must specify 'root=/dev/mmcblk1p9' in the CMDLINE variable above.
$ ~/dev/skales/mkbootimg --kernel ~/dev/kernel/arch/arm64/boot/Image \
--ramdisk ~/dev/initrd.img-4.14.0-qcomlt-arm64 \
--output ~/dev/boot.img \
--dt ~dev/dt.img \
--pagesize 4096 \
--base 0x80000000 \
--cmdline "${CMDLINE}";
Now you have a nice boot image. Boot the DragonBoard in fastboot mode by pressing the vol- button while powering it up. Boot the board with the following command:
$ fastboot boot ~/dev/boot.img
ssh to the DragonBoard, clone, compile, and install the userspace library used to communicate with the adsprpc driver.
$ cd ~
$ git clone https://git.linaro.org/people/srinivas.kandagatla/libadsprpc.git
$ cd libadsprpc/adsrpc
$ make
$ sudo cp ./libadsprpc.so /usr/local/lib/
$ sudo ldconfig
The easiest way is to install them through apt. If you're running a Debian image obtained from the 96boards website as described above, simply install them on the DragonBoard using apt:
$ sudo apt update
$ sudo apt install rmtfs qrtr libqrtr1
With these packages come the systemd startup script that configure the IPC router and start the remote filesystem service. You can skip the next chapter and Boot the remote DSP.
$ cd ~
$ git clone https://github.com/andersson/qrtr.git
$ cd qrtr
$ make
$ sudo make install
$ cd ~
$ git clone https://github.com/andersson/qmic.git
$ cd qmic
$ make
$ sudo make install
$ cd ~
$ git clone https://github.com/andersson/rmtfs.git
$ cd rmtfs
$ make
$ sudo make install
$ dd if=/dev/zero of=/boot/modem_fs1 bs=1572864 count=1
$ dd if=/dev/zero of=/boot/modem_fs2 bs=1572864 count=1
$ dd if=/dev/zero of=/boot/modem_fsc bs=1024 count=1
$ dd if=/dev/zero of=/boot/modem_fsg bs=1572864 count=1
If the above files were not already present you'll need to reboot the board so the modem is correctly initialized.
You'll have to do so after each boot of your Dragonboard. The Debian packages of these tools already take care of that for your and are started through systemd scripts.
$ sudo qrtr-cfg 1
$ sudo qrtr-ns
$ sudo rmtfs &
Start the remote DSP through its remoteproc device to load DSP firmware.
$ sudo sh -c 'echo start > /sys/devices/platform/soc/4080000.hexagon/remoteproc/remoteproc0/state'
You can test that everything works correctly by using the getserial tool from the Hexagon SDK. This tool queries the remote DSP serial number and prints it.
Fisrt copy the executable to the DragonBoard:
$ scp /PATH/TO/HEXAGON/SDK/tools/elfsigner/getserial/UbuntuARM_Release_aarch64/getserial linaro@DB_IP_ADDR:~/dev
And execute it:
$ ssh linaro@DB_IP_ADDR sudo /home/linaro/dev/getserial
If everything works correctly you should get something like:
####################Serial number (see below)###########################
Serial Num : 0xe2afec0
####################Serial number (see above)###########################
If it's not the case, please check:
- Your kernel has support for the adsprpc driver (CONFIG_MSM_ADSPRPC=y)
- Modem firmware files r1036.1 are installed in /lib/firmware on the DragonBoard
$ source /PATH/TO/HEXAGON/SDK/setup_sdk_env.source
$ cd ~/dev
$ git clone https://git.linaro.org/people/thierry.escande/matrix_multi.git
$ cd matrix_multi
$ make tree V=UbuntuARM_Debug_aarch64
$ make tree V=hexagon_Debug_dynamic
The resulting binaries will be in the following folders:
APPS: UbuntuARM_Debug_aarch64/ship
DSP: hexagon_Debug_dynamic/ship
Copy the content to the DragonBoard:
$ ssh linaro@DB_IP_ADDR mkdir /home/linaro/apps /home/linaro/dsp
$ scp matrix_multi/UbuntuARM_Debug_aarch64/ship/* linaro@DB_IP_ADDR:~/apps
$ scp matrix_multi/hexagon_Debug_dynamic/ship/* linaro@DB_IP_ADDR:~/dsp
ssh to the DragonBoard and set the library path to the apps and dsp folders:
$ sudo su
$ export ADSP_LIBRARY_PATH=/home/linaro/dsp
$ export LD_LIBRARY_PATH=/home/linaro/apps
Now you're ready to run the example:
$ cd /home/linaro/apps
$ ./matrix_multi 0 10
The matrix_multi example calculates the resulting matrix of multiplying two size x size matrices A and B, where A is a transposing matrix with a single 1 in each column and row and B has random values between 0..size-1 where size is the second parameter passed to the application. Pass 0 as first parameter to execute the multiplication on the remote DSP. Pass 1 to execute it on the application processor.