├── scripts ├── run.tcl ├── create_fsbl_project.tcl ├── 53-adi-plutosdr-usb.rules ├── target_mtd_info.key ├── get_default_envs.sh └── pluto.its ├── .gitignore ├── .gitmodules ├── README.md └── Makefile /scripts/run.tcl: -------------------------------------------------------------------------------- 1 | ## JTAG bootstrap u-boot for initial SF/SPI flash programming 2 | ## Open Xilinx Command Line Tool 3 | ## type: xmd -tcl run.tcl 4 | 5 | #fpga -f system_top.bit 6 | 7 | connect arm hw 8 | stop 9 | xreset 64 10 | 11 | source ps7_init.tcl 12 | ps7_init 13 | ps7_post_config 14 | 15 | dow u-boot.elf 16 | run 17 | disconnect 64 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Object files 2 | *.o 3 | *.ko 4 | *.obj 5 | *.elf 6 | 7 | # Precompiled Headers 8 | *.gch 9 | *.pch 10 | 11 | # Libraries 12 | *.lib 13 | *.a 14 | *.la 15 | *.lo 16 | 17 | # Shared objects (inc. Windows DLLs) 18 | *.dll 19 | *.so 20 | *.so.* 21 | *.dylib 22 | 23 | # Executables 24 | *.exe 25 | *.out 26 | *.app 27 | *.i*86 28 | *.x86_64 29 | *.hex 30 | 31 | # Debug files 32 | *.dSYM/ 33 | *.su 34 | 35 | build/ 36 | -------------------------------------------------------------------------------- /scripts/create_fsbl_project.tcl: -------------------------------------------------------------------------------- 1 | hsi open_hw_design build/system_top.hdf 2 | set cpu_name [lindex [hsi get_cells -filter {IP_TYPE==PROCESSOR}] 0] 3 | 4 | sdk set_workspace ./build/sdk 5 | sdk create_hw_project -name hw_0 -hwspec build/system_top.hdf 6 | sdk create_app_project -name fsbl -hwproject hw_0 -proc $cpu_name -os standalone -lang C -app {Zynq FSBL} 7 | sdk build_project -type all 8 | #xsdk -batch -source create_fsbl_project.tcl 9 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "u-boot-xlnx"] 2 | path = u-boot-xlnx 3 | url = https://github.com/Hoernchen/u-boot-xlnx.git 4 | branch = pluto 5 | [submodule "buildroot"] 6 | path = buildroot 7 | url = https://github.com/Hoernchen/buildroot.git 8 | branch = pluto 9 | [submodule "linux"] 10 | path = linux 11 | url = https://github.com/Hoernchen/linux 12 | branch = xcomm_zynq 13 | [submodule "hdl"] 14 | path = hdl 15 | url = https://github.com/analogdevicesinc/hdl 16 | branch = dev 17 | -------------------------------------------------------------------------------- /scripts/53-adi-plutosdr-usb.rules: -------------------------------------------------------------------------------- 1 | # allow "plugdev" group read/write access to ADI PlutoSDR devices 2 | # DFU Device 3 | SUBSYSTEM=="usb", ATTRS{idVendor}=="0456", ATTRS{idProduct}=="b674", MODE="0664", GROUP="plugdev" 4 | # SDR Device 5 | SUBSYSTEM=="usb", ATTRS{idVendor}=="0456", ATTRS{idProduct}=="b673", MODE="0664", GROUP="plugdev" 6 | # tell the ModemManager (part of the NetworkManager suite) that the device is not a modem, 7 | # and don't send AT commands to it 8 | SUBSYSTEM=="usb", ATTRS{idVendor}=="0456", ATTRS{idProduct}=="b673", ENV{ID_MM_DEVICE_IGNORE}="1" 9 | -------------------------------------------------------------------------------- /scripts/target_mtd_info.key: -------------------------------------------------------------------------------- 1 | dev: size erasesize name 2 | mtd0: 00100000 00001000 "qspi-fsbl-uboot" 3 | mtd1: 00020000 00001000 "qspi-uboot-env" 4 | mtd2: 000e0000 00001000 "qspi-nvmfs" 5 | mtd3: 01e00000 00001000 "qspi-linux" 6 | -------------------------------------------------------------------------------- /scripts/get_default_envs.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | # 3 | # Copyright (C) 2016, Lukasz Majewski 4 | # 5 | # SPDX-License-Identifier: GPL-2.0+ 6 | # 7 | 8 | # This file extracts default envs from built u-boot 9 | # usage: get_default_envs.sh > u-boot-env-default.txt 10 | set -ue 11 | 12 | ENV_OBJ_FILE="env_common.o" 13 | ENV_OBJ_FILE_COPY="copy_${ENV_OBJ_FILE}" 14 | 15 | echoerr() { echo "$@" 1>&2; } 16 | 17 | path=$(readlink -f $0) 18 | env_obj_file_path=$(find ${path%/scripts*} -not -path "*/spl/*" \ 19 | -name "${ENV_OBJ_FILE}") 20 | [ -z "${env_obj_file_path}" ] && \ 21 | { echoerr "File '${ENV_OBJ_FILE}' not found!"; exit 1; } 22 | 23 | cp ${env_obj_file_path} ${ENV_OBJ_FILE_COPY} 24 | 25 | # NOTE: objcopy saves its output to file passed in 26 | # (copy_env_common.o in this case) 27 | ${CROSS_COMPILE}objcopy -O binary -j ".rodata.default_environment" ${ENV_OBJ_FILE_COPY} 28 | 29 | # Replace default '\0' with '\n' and sort entries 30 | tr '\0' '\n' < ${ENV_OBJ_FILE_COPY} | sort -u 31 | 32 | rm ${ENV_OBJ_FILE_COPY} 33 | 34 | exit 0 35 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # *modified* plutosdr firmware 2 | This experimental **rx only** firmware uses a custom library on the host side and a kernel driver on the plutosdr itself (no libiio!) 3 | 4 | Requires https://github.com/Hoernchen/libosmoplutosdr + http://cgit.osmocom.org/gr-osmosdr/ plutokernel branch 5 | 6 | * What 7 | 8 | * RX only 9 | * Just basic functionality so far - frequency, gain, rate 10 | 11 | * Why 12 | 13 | * Libiio is the most ~contrived~ generic way for writing strings to sysfs entries i've ever seen.. I don't really want bison and flex as deps just to control my plutosdr. 14 | * Libiio is also the most generic way to transfer data from the device to the host - it's probably great as long as it's being used with USB 3.0 which hast plenty bandwidth to spare, which is not the case here. There is nothing generic about the plutosdr, making sure the samples arrive at the host is paramount. 15 | * Actual usb performance according to the usb transfer timestamps was about 220mbit/s - the kernel driver version maxes out at about 327mbit/s on my machine (Win10) 16 | * This requires a patched libusb on Windows, because the libusb maintainers couln't agree upon a platform independent way to implement windows specific flags during the past (ten?) years. 17 | 18 | 19 | * Build Instructions 20 | ```bash 21 | 22 | git clone --recursive https://github.com/Hoernchen/plutosdr-fw.git 23 | cd plutosdr-fw 24 | export CROSS_COMPILE=arm-xilinx-linux-gnueabi- 25 | export PATH=$PATH:/opt/Xilinx/SDK/2016.2/gnu/arm/lin/bin 26 | export VIVADO_SETTINGS=/opt/Xilinx/Vivado/2016.2/settings64.sh 27 | make 28 | 29 | ``` 30 | No need to flash the firmware - just switch your plutosdr to DFU mode 31 | ```bash 32 | device_reboot ram 33 | ``` 34 | then upload the firmware 35 | ```bash 36 | dfu-util -D pluto.dfu -a firmware.dfu 37 | dfu-util -e 38 | ``` 39 | -------------------------------------------------------------------------------- /scripts/pluto.its: -------------------------------------------------------------------------------- 1 | /* 2 | * U-Boot uImage source file with multiple kernels, ramdisks and FDT blobs 3 | * This example makes use of the 'loadables' field 4 | */ 5 | 6 | /* 7 | * fdt get addr foo /images/fdt@1 data 8 | */ 9 | 10 | /dts-v1/; 11 | 12 | / { 13 | description = "Configuration to load fpga before Kernel"; 14 | magic = "ITB PlutoSDR (ADALM-PLUTO)"; 15 | #address-cells = <1>; 16 | images { 17 | 18 | fdt@1 { 19 | description = "zynq-pluto-sdr"; 20 | data = /incbin/("../build/zynq-pluto-sdr.dtb"); 21 | type = "flat_dt"; 22 | arch = "arm"; 23 | compression = "none"; 24 | }; 25 | 26 | fdt@2 { 27 | description = "zynq-pluto-sdr-revb"; 28 | data = /incbin/("../build/zynq-pluto-sdr-revb.dtb"); 29 | type = "flat_dt"; 30 | arch = "arm"; 31 | compression = "none"; 32 | }; 33 | 34 | fpga@1 { 35 | description = "FPGA"; 36 | data = /incbin/("../build/system_top.bit"); 37 | type = "fpga"; 38 | arch = "arm"; 39 | compression = "none"; 40 | load = <0xF000000>; 41 | hash@1 { 42 | algo = "md5"; 43 | }; 44 | }; 45 | 46 | linux_kernel@1 { 47 | description = "Linux"; 48 | data = /incbin/("../build/zImage"); 49 | type = "kernel"; 50 | arch = "arm"; 51 | os = "linux"; 52 | compression = "none"; 53 | load = <0x8000>; 54 | entry = <0x8000>; 55 | hash@1 { 56 | algo = "md5"; 57 | }; 58 | }; 59 | ramdisk@1 { 60 | description = "Ramdisk"; 61 | data = /incbin/("../build/rootfs.cpio.gz"); 62 | type = "ramdisk"; 63 | arch = "arm"; 64 | os = "linux"; 65 | compression = "gzip"; 66 | hash@1 { 67 | algo = "md5"; 68 | }; 69 | }; 70 | 71 | }; 72 | 73 | configurations { 74 | default = "config@0"; 75 | config@0 { 76 | description = "Linux with fpga RevA"; 77 | fdt = "fdt@1"; 78 | kernel = "linux_kernel@1"; 79 | ramdisk = "ramdisk@1"; 80 | fpga = "fpga@1"; 81 | }; 82 | 83 | /* all below is currently RevB ! */ 84 | 85 | config@1 { 86 | description = "Linux with fpga RevB"; 87 | fdt = "fdt@2"; 88 | kernel = "linux_kernel@1"; 89 | ramdisk = "ramdisk@1"; 90 | fpga = "fpga@1"; 91 | }; 92 | 93 | config@2 { 94 | description = "Linux with fpga RevB"; 95 | fdt = "fdt@2"; 96 | kernel = "linux_kernel@1"; 97 | ramdisk = "ramdisk@1"; 98 | fpga = "fpga@1"; 99 | }; 100 | 101 | config@3 { 102 | description = "Linux with fpga RevB"; 103 | fdt = "fdt@2"; 104 | kernel = "linux_kernel@1"; 105 | ramdisk = "ramdisk@1"; 106 | fpga = "fpga@1"; 107 | }; 108 | 109 | config@4 { 110 | description = "Linux with fpga RevB"; 111 | fdt = "fdt@2"; 112 | kernel = "linux_kernel@1"; 113 | ramdisk = "ramdisk@1"; 114 | fpga = "fpga@1"; 115 | }; 116 | 117 | config@5 { 118 | description = "Linux with fpga RevB"; 119 | fdt = "fdt@2"; 120 | kernel = "linux_kernel@1"; 121 | ramdisk = "ramdisk@1"; 122 | fpga = "fpga@1"; 123 | }; 124 | 125 | config@6 { 126 | description = "Linux with fpga RevB"; 127 | fdt = "fdt@2"; 128 | kernel = "linux_kernel@1"; 129 | ramdisk = "ramdisk@1"; 130 | fpga = "fpga@1"; 131 | }; 132 | 133 | 134 | config@7 { 135 | description = "Linux with fpga RevB"; 136 | fdt = "fdt@2"; 137 | kernel = "linux_kernel@1"; 138 | ramdisk = "ramdisk@1"; 139 | fpga = "fpga@1"; 140 | }; 141 | 142 | config@8 { 143 | description = "Linux with fpga RevB"; 144 | fdt = "fdt@2"; 145 | kernel = "linux_kernel@1"; 146 | ramdisk = "ramdisk@1"; 147 | fpga = "fpga@1"; 148 | }; 149 | 150 | config@9 { /* This one is actually RevB */ 151 | description = "Linux with fpga RevB"; 152 | fdt = "fdt@2"; 153 | kernel = "linux_kernel@1"; 154 | ramdisk = "ramdisk@1"; 155 | fpga = "fpga@1"; 156 | }; 157 | 158 | config@10 { 159 | description = "Linux with fpga RevB"; 160 | fdt = "fdt@2"; 161 | kernel = "linux_kernel@1"; 162 | ramdisk = "ramdisk@1"; 163 | fpga = "fpga@1"; 164 | }; 165 | }; 166 | }; 167 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | #PATH=$PATH:/opt/Xilinx/SDK/2015.4/gnu/arm/lin/bin 2 | 3 | CROSS_COMPILE ?= arm-xilinx-linux-gnueabi- 4 | 5 | NCORES = $(shell grep -c ^processor /proc/cpuinfo) 6 | VIVADO_SETTINGS ?= /opt/Xilinx/Vivado/2016.2/settings64.sh 7 | VSUBDIRS = hdl buildroot linux 8 | 9 | VERSION=$(shell git describe --abbrev=4 --dirty --always --tags) 10 | UBOOT_VERSION=$(shell echo -n "PlutoSDR " && cd u-boot-xlnx && git describe --abbrev=0 --dirty --always --tags) 11 | 12 | 13 | ifeq (, $(shell which dfu-suffix)) 14 | $(warning "No dfu-utils in PATH consider doing: sudo apt-get install dfu-util") 15 | TARGETS = build/pluto.frm build/boot.frm 16 | else 17 | TARGETS = build/pluto.dfu build/boot.dfu build/uboot-env.dfu build/pluto.frm build/boot.frm 18 | endif 19 | 20 | all: $(TARGETS) zip-all jtag-bootstrap 21 | 22 | build: 23 | mkdir -p $@ 24 | 25 | %: build/% 26 | cp $< $@ 27 | 28 | ### u-boot ### 29 | 30 | u-boot-xlnx/u-boot u-boot-xlnx/tools/mkimage: 31 | make -C u-boot-xlnx ARCH=arm zynq_pluto_defconfig 32 | make -C u-boot-xlnx ARCH=arm CROSS_COMPILE=$(CROSS_COMPILE) UBOOTVERSION="$(UBOOT_VERSION)" 33 | 34 | .PHONY: u-boot-xlnx/u-boot 35 | 36 | build/u-boot.elf: u-boot-xlnx/u-boot | build 37 | cp $< $@ 38 | 39 | build/uboot-env.txt: u-boot-xlnx/u-boot | build 40 | CROSS_COMPILE=$(CROSS_COMPILE) scripts/get_default_envs.sh > $@ 41 | 42 | build/uboot-env.bin: build/uboot-env.txt 43 | u-boot-xlnx/tools/mkenvimage -s 0x20000 -o $@ $< 44 | 45 | ### Linux ### 46 | 47 | linux/arch/arm/boot/zImage: 48 | make -C linux ARCH=arm zynq_pluto_defconfig 49 | make -C linux -j $(NCORES) ARCH=arm CROSS_COMPILE=$(CROSS_COMPILE) zImage UIMAGE_LOADADDR=0x8000 50 | make -C linux -j $(NCORES) ARCH=arm CROSS_COMPILE=$(CROSS_COMPILE) modules 51 | make -C linux -j $(NCORES) ARCH=arm CROSS_COMPILE=$(CROSS_COMPILE) INSTALL_MOD_PATH=${PWD}/buildroot/output/target modules_install 52 | 53 | .PHONY: linux/arch/arm/boot/zImage 54 | 55 | 56 | build/zImage: linux/arch/arm/boot/zImage | build 57 | cp $< $@ 58 | 59 | ### Device Tree ### 60 | 61 | linux/arch/arm/boot/dts/%.dtb: linux/arch/arm/boot/dts/%.dts linux/arch/arm/boot/dts/zynq-pluto-sdr.dtsi 62 | make -C linux -j $(NCORES) ARCH=arm CROSS_COMPILE=$(CROSS_COMPILE) $(notdir $@) 63 | 64 | build/%.dtb: linux/arch/arm/boot/dts/%.dtb | build 65 | cp $< $@ 66 | 67 | ### Buildroot ### 68 | 69 | buildroot/output/images/rootfs.cpio.gz: 70 | @echo device-fw $(VERSION)> $(CURDIR)/buildroot/board/pluto/VERSIONS 71 | @$(foreach dir,$(VSUBDIRS),echo $(dir) $(shell cd $(dir) && git describe --abbrev=4 --dirty --always --tags) >> $(CURDIR)/buildroot/board/pluto/VERSIONS;) 72 | make -C buildroot ARCH=arm zynq_pluto_defconfig 73 | make -C buildroot TOOLCHAIN_EXTERNAL_INSTALL_DIR= ARCH=arm CROSS_COMPILE=$(CROSS_COMPILE) BUSYBOX_CONFIG_FILE=$(CURDIR)/buildroot/board/pluto/busybox-1.25.0.config all 74 | 75 | .PHONY: buildroot/output/images/rootfs.cpio.gz 76 | 77 | build/rootfs.cpio.gz: buildroot/output/images/rootfs.cpio.gz | build 78 | cp $< $@ 79 | 80 | build/pluto.itb: u-boot-xlnx/tools/mkimage build/zImage build/rootfs.cpio.gz build/zynq-pluto-sdr.dtb build/zynq-pluto-sdr-revb.dtb build/system_top.bit 81 | u-boot-xlnx/tools/mkimage -f scripts/pluto.its $@ 82 | 83 | build/system_top.hdf: | build 84 | # wget -T 3 -t 1 -N --directory-prefix build http://10.50.1.20/jenkins_export/hdl/dev/pluto/latest/system_top.hdf || bash -c "source $(VIVADO_SETTINGS) && make -C hdl projects/pluto && cp hdl/projects/pluto/pluto.sdk/system_top.hdf $@" 85 | bash -c "source $(VIVADO_SETTINGS) && make -C hdl/projects/pluto && cp hdl/projects/pluto/pluto.sdk/system_top.hdf $@" 86 | 87 | ### TODO: Build system_top.hdf from src if dl fails - need 2016.2 for that ... 88 | 89 | build/sdk/fsbl/Release/fsbl.elf build/sdk/hw_0/system_top.bit : build/system_top.hdf 90 | rm -Rf build/sdk 91 | bash -c "source $(VIVADO_SETTINGS) && xsdk -batch -source scripts/create_fsbl_project.tcl" 92 | 93 | build/system_top.bit: build/sdk/hw_0/system_top.bit 94 | cp $< $@ 95 | 96 | build/boot.bin: build/sdk/fsbl/Release/fsbl.elf build/u-boot.elf 97 | @echo img:{[bootloader] $^ } > build/boot.bif 98 | bash -c "source $(VIVADO_SETTINGS) && bootgen -image build/boot.bif -w -o $@" 99 | 100 | ### MSD update firmware file ### 101 | 102 | build/pluto.frm: build/pluto.itb 103 | md5sum $< | cut -d ' ' -f 1 > $@.md5 104 | cat $< $@.md5 > $@ 105 | 106 | build/boot.frm: build/boot.bin build/uboot-env.bin scripts/target_mtd_info.key 107 | cat $^ | tee $@ | md5sum | cut -d ' ' -f1 | tee -a $@ 108 | 109 | ### DFU update firmware file ### 110 | 111 | build/%.dfu: build/%.bin 112 | cp $< $<.tmp 113 | dfu-suffix -a $<.tmp -v 0x0456 -p 0xb673 114 | mv $<.tmp $@ 115 | 116 | build/pluto.dfu: build/pluto.itb 117 | cp $< $<.tmp 118 | dfu-suffix -a $<.tmp -v 0x0456 -p 0xb673 119 | mv $<.tmp $@ 120 | 121 | clean-build: 122 | rm -f $(notdir $(wildcard build/*)) 123 | rm -rf build/* 124 | 125 | clean: 126 | make -C u-boot-xlnx clean 127 | make -C linux clean 128 | make -C buildroot clean 129 | make -C hdl clean 130 | rm -f $(notdir $(wildcard build/*)) 131 | rm -rf build/* 132 | 133 | zip-all: $(TARGETS) 134 | zip -j build/plutosdr-fw-$(VERSION).zip $^ 135 | 136 | dfu-pluto: build/pluto.dfu 137 | dfu-util -D build/pluto.dfu -a firmware.dfu 138 | dfu-util -e 139 | 140 | dfu-sf-uboot: build/boot.dfu build/uboot-env.dfu 141 | echo "Erasing u-boot be careful - Press Return to continue... " && read key && \ 142 | dfu-util -D build/boot.dfu -a boot.dfu && \ 143 | dfu-util -D build/uboot-env.dfu -a uboot-env.dfu 144 | dfu-util -e 145 | 146 | dfu-all: build/pluto.dfu build/boot.dfu build/uboot-env.dfu 147 | echo "Erasing u-boot be careful - Press Return to continue... " && read key && \ 148 | dfu-util -D build/pluto.dfu -a firmware.dfu && \ 149 | dfu-util -D build/boot.dfu -a boot.dfu && \ 150 | dfu-util -D build/uboot-env.dfu -a uboot-env.dfu 151 | dfu-util -e 152 | 153 | dfu-ram: build/pluto.dfu 154 | sshpass -p analog ssh root@pluto '/usr/sbin/device_reboot ram;' 155 | sleep 5 156 | dfu-util -D build/pluto.dfu -a firmware.dfu 157 | dfu-util -e 158 | 159 | jtag-bootstrap: build/u-boot.elf build/sdk/hw_0/ps7_init.tcl build/sdk/hw_0/system_top.bit scripts/run.tcl 160 | $(CROSS_COMPILE)strip build/u-boot.elf 161 | zip -j build/plutosdr-$@-$(VERSION).zip $^ 162 | 163 | git-update-all: 164 | git submodule update --recursive --remote 165 | 166 | git-pull: 167 | git pull --recurse-submodules 168 | --------------------------------------------------------------------------------