-
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 Dragonboard 410c and 820c.
- Environment Setup
- Install Linaro Toolchain
- Install Hexagon SDK
- Build Kernel
- Build libadsprpc.so and adsprpcd
- Copy libadsprpc.so to Hexagon SDK
- Setup userspace tools
- Building matrix_multi application
- Linux based host machine.
- DragonBoard 410c or 820c 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.
- For db410c, you need the apq8016 modem firmware files r1036.1 to get FastRPC support. These files are 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 db820c, the public archive linux-board-support-package-r01700.1.zip contains the needed adsp firwmares.
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.
Eventually you may add the bin sub-folder of the Linaro toolchain to your $PATH environment variable. This is needed to cross-compile libadsprpc.so if you want to build it from your host.
You need to install the Hexagon SDK to compile the sample application. The SDK can be downloaded here. You can choose version 3.4.1.
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
Then use your favorite kernel configuration habit to enable a few more options:
CONFIG_QCOM_FASTRPC=y (Device Drivers -> Misc devices)
For db820c you must enable the Qualcomm Asynchronous Packet Router
CONFIG_QCOM_APR=y (Device Drivers -> SOC (System On Chip) specific Drivers -> Qualcomm SoC drivers)
Then built it:
$ 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
This userspace library is used to communicate with the adsprpc driver. It can be cross-compiled on your host machine or directly on the DragonBoard.
You'll also need to copy it onto the Hexagon SDK so the sample applications use it and not the default stubbed libraries provided by the SDK.
First git clone the repo:
$ cd ~/dev
$ git clone https://git.linaro.org/people/srinivas.kandagatla/libadsprpc.git
$ cd libadsprpc
Use the gitcompile script to configure it.
Use the --host option if you are cross-compiling (you need the Linaro toolchain in your $PATH).
$ ./gitcompile [--host=aarch64-linux-gnu]
Then build and install!
$ make
$ sudo make install
If you cross-compile from your host machine you obviously need to copy the binaries onto your target device. Once built they are located here:
src/lib/.libs/libadsprpc.so*
src/utils/.libs/adsprpcd
It's time to hack around with the Hexagon SDK. Copy the library binaries to the SDK for the UbuntuARM target:
$ cp src/lib/.libs/libadsprpc.so* $HEXAGON_SDK_ROOT/libs/common/remote/ship/UbuntuARM_Debug_aarch64/
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.
On db820c you need to execute the adsprpcd daemon. This daemon is responsible for loading the hexagon code to the DSP.
$ sudo adsprpcd &
Then copy the getserial 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 V=hexagon_Debug_dynamic_toolv82_v60 tree
$ make V=UbuntuARM_Debug_aarch64 tree
The resulting binaries will be in the following folders:
DSP: hexagon_Debug_dynamic_toolv82_v60/ship
APPS: UbuntuARM_Debug_aarch64/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
For db410c, copy the DSP library:
$ scp matrix_multi/hexagon_Debug_dynamic_toolv82_v60/ship/*.so linaro@DB_IP_ADDR:~/dsp
For db820c, you first need to sign the DSP library and copy it:
$ python $HEXAGON_SDK_ROOT/tools/elfsigner/elfsigner.py -i ./hexagon_Debug_dynamic_toolv82_v60/ship/libmatrix_multi_skel.so
$ scp output/*.so 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.