1
0
Fork 0

Compare commits

...

13 Commits

10 changed files with 486 additions and 135 deletions

View File

@ -0,0 +1,141 @@
# Fix for bus error issues when compiling cpython extensions in pyrp3 v1.2.0+
# Patch sourced from: https://github.com/linien-org/pyrp3/tree/e6688acf8bd79d2dbe1d192d09c1a1baf1f6c67b (setup.py & monitor/Makefile)
# Reference: https://github.com/elhep/Fast-Servo-Firmware/blob/master/OS/scripts/linien_install_requirements.sh#L28
diff --git a/monitor/Makefile b/monitor/Makefile
new file mode 100644
index 0000000..044d88e
--- /dev/null
+++ b/monitor/Makefile
@@ -0,0 +1,31 @@
+# Makefile for libmonitor
+
+OBJS = monitor.o
+SRCS = $(subst .o,.c, $(OBJS))
+OSOBJS = monitor.os
+TARGETLIB=libmonitor.so
+CFLAGS=-g -std=gnu99 -Wall -Werror
+LIBS=-lm -lpthread
+
+# Use CROSS_COMPILE=arm-linux-gnueabi-
+CC=$(CROSS_COMPILE)gcc
+INSTALL_DIR ?= .
+
+
+all: $(TARGETLIB)
+lib: $(TARGETLIB)
+
+%.os: %.c
+ $(CC) -c -fPIC $(CFLAGS) $< -o $@
+
+$(TARGETLIB): $(OSOBJS)
+ $(CC) -o $@ -shared $^ $(CFLAGS) $(LIBS)
+
+clean:
+ rm -f $(TARGETLIB) *.o *.os
+
+# Install target - creates 'lib/' sub-directory in $(INSTALL_DIR) and copies all
+# executables to that location.
+install:
+ mkdir -p $(INSTALL_DIR)/lib
+ cp $(TARGETLIB) $(INSTALL_DIR)/lib
\ No newline at end of file
diff --git a/pyrp3/raw_memory.py b/pyrp3/raw_memory.py
index ce1b28e..233b82a 100644
--- a/pyrp3/raw_memory.py
+++ b/pyrp3/raw_memory.py
@@ -1,12 +1,9 @@
from ctypes import POINTER, c_uint32, cast, cdll, create_string_buffer, sizeof
-from importlib.machinery import EXTENSION_SUFFIXES
from pathlib import Path
import numpy as np
-libmonitor_file = str(
- Path(__file__).parent / ".." / "monitor{}".format(EXTENSION_SUFFIXES[0])
-)
+libmonitor_file = 'libmonitor.so'
libmonitor = cdll.LoadLibrary(libmonitor_file)
libmonitor.read_value.restype = c_uint32
diff --git a/setup.py b/setup.py
index 98bdaee..b0a8af4 100644
--- a/setup.py
+++ b/setup.py
@@ -1,5 +1,10 @@
import re
-from distutils.core import Extension, setup
+import os
+
+from distutils.core import setup
+from distutils.command.build import build
+from distutils.command.install import install
+
from pathlib import Path
# from https://stackoverflow.com/a/7071358/2750945
@@ -11,9 +16,50 @@ if mo:
verstr = mo.group(1)
else:
raise RuntimeError("Unable to find version string in %s." % (VERSIONFILE,))
+
+# Patch from https://github.com/linien-org/pyrp3/blob/e6688acf8bd79d2dbe1d192d09c1a1baf1f6c67b/setup.py#L16-L55
+build_dir = "monitor/"
+
+def compile_libmonitor():
+ cwd = os.getcwd() # get current directory
+ try:
+ os.chdir(build_dir)
+ os.system("make clean")
+ os.system("make all")
+ finally:
+ os.chdir(cwd)
+
+
+def install_libmonitor(prefix=""):
+ cwd = os.getcwd() # get current directory
+ try:
+ os.chdir(build_dir)
+ os.system("make install INSTALL_DIR={prefix}".format(prefix=prefix))
+ finally:
+ os.chdir(cwd)
+
+
+class lib_build(build):
+ def run(self):
+ compile_libmonitor()
+ build.run(self)
+
+
+class lib_install(install):
+ def run(self):
+ compile_libmonitor()
+ install_libmonitor(self.prefix)
+ # install.run(self)
+
+# Will use nix to install libmonitor
+cmdclass = {
+ "build": lib_build
+}
+
this_directory = Path(__file__).parent
long_description = (this_directory / "README.rst").read_text()
+
setup(
name="pyrp3",
version=verstr,
@@ -32,6 +78,7 @@ setup(
"cached_property>=1.5.2",
"numpy>=1.11.0",
],
+ cmdclass=cmdclass,
classifiers=[
"Intended Audience :: Developers",
"Intended Audience :: Education",
@@ -45,5 +92,4 @@ setup(
"Topic :: Software Development :: Libraries :: Python Modules",
],
keywords=["redpitaya", "FPGA", "zynq"],
- ext_modules=[Extension("monitor", ["monitor/monitor.c"])],
)

View File

@ -21,7 +21,7 @@ import mmap
import os import os
import spidev import spidev
from common import ( from pyfastservo.common import (
ADC_AFE_CTRL_ADDR, ADC_AFE_CTRL_ADDR,
ADC_BITSLIP_ADDR, ADC_BITSLIP_ADDR,
ADC_CH0_HIGH_ADDR, ADC_CH0_HIGH_ADDR,
@ -54,7 +54,7 @@ def main_adc_config(test_pattern):
spi.open(MAIN_ADC_BUS, MAIN_ADC_DEVICE) spi.open(MAIN_ADC_BUS, MAIN_ADC_DEVICE)
spi.max_speed_hz = 50000 spi.max_speed_hz = 50000
spi.mode = 0b00 # CPOL = 0 CPHA = 0 spi.mode = 0b00 # CPOL = 0 CPHA = 0
spi.cshigh = True spi.cshigh = False
# spi.read0 = False # spi.read0 = False
spi_buffer = [0x00, 0x80] # reset spi_buffer = [0x00, 0x80] # reset
@ -121,7 +121,7 @@ def main_adc_test_mode(enable):
spi.open(MAIN_ADC_BUS, MAIN_ADC_DEVICE) spi.open(MAIN_ADC_BUS, MAIN_ADC_DEVICE)
spi.max_speed_hz = 50000 spi.max_speed_hz = 50000
spi.mode = 0b00 # CPOL = 0 CPHA = 0 spi.mode = 0b00 # CPOL = 0 CPHA = 0
spi.cshigh = True spi.cshigh = False
# spi.read0 = True # spi.read0 = True
reg_contents = ( reg_contents = (
@ -292,7 +292,7 @@ def adc_aux_read(port, type, pin):
spi.open(1, 3) # AUX ADC 1? spi.open(1, 3) # AUX ADC 1?
spi.max_speed_hz = 5000 spi.max_speed_hz = 5000
spi.mode = 0b00 spi.mode = 0b00
spi.cshigh = True spi.cshigh = False
read_buffer = spi.xfer2(write_buffer) read_buffer = spi.xfer2(write_buffer)
mu_voltage = read_buffer[0] << 8 | read_buffer[1] >> 2 mu_voltage = read_buffer[0] << 8 | read_buffer[1] >> 2

View File

@ -22,8 +22,8 @@ MAP_SIZE = 0x1000
MAP_MASK = 0xFFF MAP_MASK = 0xFFF
PAGESIZE = 0x1000 PAGESIZE = 0x1000
LINIEN_OFFSET = 0x0 # LINIEN_OFFSET = 0x0
# LINIEN_OFFSET = 0x300000 LINIEN_OFFSET = 0x300000
# ---------------------------------------------------------------- # ----------------------------------------------------------------
# FRONT PANEL LEDS REGISTER ADDRESSES # FRONT PANEL LEDS REGISTER ADDRESSES

View File

@ -21,7 +21,7 @@ import mmap
import os import os
import spidev import spidev
from common import ( from pyfastservo.common import (
CH0_HIGH_WORD_ADDR, CH0_HIGH_WORD_ADDR,
CH0_LOW_WORD_ADDR, CH0_LOW_WORD_ADDR,
CH1_HIGH_WORD_ADDR, CH1_HIGH_WORD_ADDR,
@ -45,7 +45,7 @@ def main_dac_init():
spi.open(MAIN_DAC_BUS, MAIN_DAC_DEVICE) spi.open(MAIN_DAC_BUS, MAIN_DAC_DEVICE)
spi.max_speed_hz = 5000 spi.max_speed_hz = 5000
spi.mode = 0b00 # CPOL = 0 CPHA = 0 spi.mode = 0b00 # CPOL = 0 CPHA = 0
spi.cshigh = True spi.cshigh = False
spi_buffer = [0x00, 0x10] # software reset spi_buffer = [0x00, 0x10] # software reset
spi.xfer2(spi_buffer) spi.xfer2(spi_buffer)

View File

@ -21,7 +21,7 @@ import mmap
import os import os
import time import time
from common import ( from pyfastservo.common import (
LED0_BASE_ADDR, LED0_BASE_ADDR,
LED1_BASE_ADDR, LED1_BASE_ADDR,
LED2_BASE_ADDR, LED2_BASE_ADDR,

View File

@ -17,9 +17,7 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>. # along with this program. If not, see <https://www.gnu.org/licenses/>.
import adc from pyfastservo import adc, si5340, dac
import si5340
import dac
def main(): def main():
si5340.configure_si5340() si5340.configure_si5340()

View File

@ -17,102 +17,255 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>. # along with this program. If not, see <https://www.gnu.org/licenses/>.
# Additional Reference:
# https://github.com/torvalds/linux/blob/master/drivers/clk/clk-si5341.c
import time
from smbus2 import SMBus from smbus2 import SMBus
BUS_NO = 0 BUS_NO = 0
IC_ADDR = 0x74 IC_ADDR = 0x74
PAGE_ADDR = 0x1 DEVICE_READY = 0x00FE
PLL_M_DEN = 0x023B
STATUS = 0x000C
STATUS_STICKY = 0x0011
OUT0_MUX_SEL_ADDR = 0x15 STATUS_LOSREF = 0x04
OUT1_MUX_SEL_ADDR = 0x1A STATUS_LOL = 0x08
OUT2_MUX_SEL_ADDR = 0x29
OUT3_MUX_SEL_ADDR = 0x2E
OUT2_AMPL_ADDR = 0x28
OUT3_PDN_ADDR = 0x2B
OUT3_FORMAT_ADDR = 0x2C
OUT3_AMPL_ADDR = 0x2D
N1_DIVIDER_UPDATE_ADDR = 0x17 def write_preamble(bus):
preamble = [
(0x0B24, 0xC0),
(0x0B25, 0x00),
(0x0502, 0x01),
(0x0505, 0x03),
(0x0957, 0x17),
(0x0B4E, 0x1A),
]
for address, value in preamble:
bus.write_byte_data(IC_ADDR, address, value)
data_to_write = 0 def write_postamble(bus):
clk_out_addr = [ postamble = [
OUT0_MUX_SEL_ADDR, (0x001C, 0x01), # Soft reset
OUT1_MUX_SEL_ADDR, (0x0B24, 0xC3),
OUT2_MUX_SEL_ADDR, (0x0B25, 0x02),
OUT3_MUX_SEL_ADDR, ]
] for address, value in postamble:
bus.write_byte_data(IC_ADDR, address, value)
def wait_device_ready(bus):
for _ in range(15):
if bus.read_byte_data(IC_ADDR, DEVICE_READY) == 0x0F:
return True
time.sleep(0.02)
return False
def wait_for_lock(bus):
for _ in range(10):
status = bus.read_byte_data(IC_ADDR, STATUS)
if not (status & (STATUS_LOSREF | STATUS_LOL)):
return True
time.sleep(0.01)
return False
def check_pll_status(bus):
pll_status = bus.read_byte_data(IC_ADDR, 0x0C)
pll_locked = not (pll_status & STATUS_LOL)
print(f"PLL {'locked' if pll_locked else 'unlocked'}")
return pll_locked
def check_los_status(bus):
los_status = bus.read_byte_data(IC_ADDR, 0x0D)
xaxb_los = (los_status & 0x10) != 0
print(f"XA/XB LOS {'asserted' if xaxb_los else 'deasserted'}")
return not xaxb_los
def configure_si5340(): def configure_si5340():
with SMBus(BUS_NO) as bus: with SMBus(BUS_NO) as bus:
if not wait_device_ready(bus):
print("Device not ready. Aborting.")
return
bus.write_byte_data(IC_ADDR, PAGE_ADDR, 0x0) # setting page to page 0 # Programming sequence from ClockBuilder Pro, default settings
# to initialize system using XTAL input
main_config = [
(0x0006, 0x00), # TOOL_VERSION
(0x0007, 0x00), # Not in datasheet
(0x0008, 0x00), # Not in datasheet
(0x000B, 0x74), # I2C_ADDR
(0x0017, 0xD0), # INT mask (disable interrupts)
(0x0018, 0xFF), # INT mask
(0x0021, 0x0F), # Select XTAL as input
(0x0022, 0x00), # Not in datasheet
(0x002B, 0x02), # SPI config
(0x002C, 0x20), # LOS enable for XTAL
(0x002D, 0x00), # LOS timing
(0x002E, 0x00), # LOS trigger (thresholds)
(0x002F, 0x00),
(0x0030, 0x00),
(0x0031, 0x00),
(0x0032, 0x00),
(0x0033, 0x00),
(0x0034, 0x00),
(0x0035, 0x00), # LOS trigger (thresholds) end
(0x0036, 0x00), # LOS clear (thresholds)
(0x0037, 0x00),
(0x0038, 0x00),
(0x0039, 0x00),
(0x003A, 0x00),
(0x003B, 0x00),
(0x003C, 0x00),
(0x003D, 0x00), # LOS clear (thresholds) end
(0x0041, 0x00), # LOS0_DIV_SEL
(0x0042, 0x00), # LOS1_DIV_SEL
(0x0043, 0x00), # LOS2_DIV_SEL
(0x0044, 0x00), # LOS3_DIV_SEL
(0x009E, 0x00), # LOL_SET_THR
(0x0102, 0x01), # Enable outputs
(0x013F, 0x00), # OUTX_ALWAYS_ON
(0x0140, 0x00), # OUTX_ALWAYS_ON
(0x0141, 0x40), # OUT_DIS_LOL_MSK, OUT_DIS_MSK_LOS_PFD
(0x0202, 0x00), # XAXB_FREQ_OFFSET (=0)
# read device id # PLL Configuration
low_word = bus.read_byte_data(IC_ADDR, 0x2) (0x0235, 0x00), # M_NUM
high_word = bus.read_byte_data(IC_ADDR, 0x3) (0x0236, 0x00),
(0x0237, 0x00),
(0x0238, 0x80),
(0x0239, 0x89),
(0x023A, 0x00),
(0x023B, 0x00), # M_DEN
(0x023C, 0x00),
(0x023D, 0x00),
(0x023E, 0x80),
print(f"DEV ID: 0x{high_word:2x}{low_word:2x}") # Synthesizer configuration
(0x0302, 0x00), # N0_NUM
(0x0303, 0x00),
(0x0304, 0x00),
(0x0305, 0x00),
(0x0306, 0x21),
(0x0307, 0x00),
(0x0308, 0x00), # N0_DEN
(0x0309, 0x00),
(0x030A, 0x00),
(0x030B, 0x80),
(0x030C, 0x01), # N0_UPDATE
data_to_write = 0x1 # N1 Configuration (1:1 ratio)
bus.write_byte_data( (0x030D, 0x00), # N1_NUM
IC_ADDR, PAGE_ADDR, data_to_write (0x030E, 0x00),
) # change to page 1 for output settings (0x030F, 0x00),
(0x0310, 0x00),
(0x0311, 0x00),
(0x0312, 0x01),
(0x0313, 0x00), # N1_DEN
(0x0314, 0x00),
(0x0315, 0x00),
(0x0316, 0x01),
(0x0317, 0x01), # N1_UPDATE
readback = bus.read_byte_data(IC_ADDR, PAGE_ADDR) # N2 Configuration (1:1 ratio)
if data_to_write != readback: (0x0318, 0x00), # N2_NUM
raise ValueError(f"Failed to set page.") (0x0319, 0x00),
(0x031A, 0x00),
(0x031B, 0x00),
(0x031C, 0x00),
(0x031D, 0x01),
(0x031E, 0x00), # N2_DEN
(0x031F, 0x00),
(0x0320, 0x00),
(0x0321, 0x01),
(0x0322, 0x01), # N2_UPDATE
for addr in clk_out_addr: # N3 Configuration (1:1 ratio)
bus.write_byte_data(IC_ADDR, addr, 1) # set source to N1 (0x0323, 0x00), # N3_NUM
(0x0324, 0x00),
(0x0325, 0x00),
(0x0326, 0x00),
(0x0327, 0x00),
(0x0328, 0x01),
(0x0329, 0x00), # N3_DEN
(0x032A, 0x00),
(0x032B, 0x00),
(0x032C, 0x01),
(0x032D, 0x01), # N3_UPDATE
bus.write_byte_data(IC_ADDR, OUT2_AMPL_ADDR, 13) # Output configuration
readback = bus.read_byte_data(IC_ADDR, OUT2_AMPL_ADDR) (0x0112, 0x06), # OUT0 config
# if data_to_write != readback: (0x0113, 0x09), # OUT0 format
# raise ValueError(f"Problematic read: {readback}.") (0x0114, 0x3B), # OUT0 CM/AMPL
(0x0115, 0x28), # OUT0 MUX_SEL
bus.write_byte_data(IC_ADDR, OUT2_AMPL_ADDR, 0x6B) # setting OUT2 to LVDS25 (0x0117, 0x06), # OUT1 config
(0x0118, 0x09), # OUT1 format
(0x0119, 0x3B), # OUT1 CM/AMPL
(0x011A, 0x28), # OUT1 MUX_SEL
bus.write_byte_data(IC_ADDR, OUT3_FORMAT_ADDR, 0xCC) # SETTING out3 to LVCMOS 18 (0x0126, 0x06), # OUT2 config
# bus.write_byte_data(IC_ADDR, 0x2E, 0x09) # SETTING out3 to LVCMOS 33 (0x0127, 0x09), # OUT2 format
(0x0128, 0x3B), # OUT2 CM/AMPL
(0x0129, 0x28), # OUT2 MUX_SEL
readback = bus.read_byte_data(IC_ADDR, OUT3_PDN_ADDR) (0x012B, 0x06), # OUT3 config
print(f"Si5340 OUTx_PDN CLK3: 0x{readback}") (0x012C, 0xCC), # OUT3 format
(0x012D, 0x00), # OUT3 CM/AMPL
(0x012E, 0x58), # OUT3 MUX_SEL
readback = bus.read_byte_data(IC_ADDR, OUT3_FORMAT_ADDR) # Miscellaneous configuration
print(f"Si5340 OUTx_FORMAT CLK3: 0x{readback}") (0x090E, 0x02), # XAXB_EXTCLK_EN=0 XAXB_PDNB=1 (use XTAL)
(0x091C, 0x04), # ZDM_EN=4 (Normal mode)
(0x0943, 0x00), # IO_VDD_SEL
(0x0949, 0x00), # IN_EN (disable input clocks)
(0x094A, 0x00), # INx_TO_PFD_EN (disabled)
(0x094E, 0x49), # REFCLK_HYS_SEL (set by CBPro)
(0x094F, 0x02), # Not in datasheet
(0x095E, 0x00), # M_INTEGER (set by CBPro)
(0x0A02, 0x00), # N_ADD_0P5 (set by CBPro)
(0x0A03, 0x01), # N_CLK_TO_OUTX_EN
(0x0A04, 0x01), # N_PIBYP
(0x0A05, 0x01), # N_PDNB
(0x0A14, 0x00), # N0_HIGH_FREQ (set by CBPro)
(0x0A1A, 0x00), # N1_HIGH_FREQ (set by CBPro)
(0x0A20, 0x00), # N2_HIGH_FREQ (set by CBPro)
(0x0A26, 0x00), # N3_HIGH_FREQ (set by CBPro)
(0x0B44, 0x0F), # PDIV_ENB (set by CBPro)
(0x0B4A, 0x0E), # N_CLK_DIS
(0x0B57, 0x0E), # VCO_RESET_CALCODE (set by CBPro)
(0x0B58, 0x01), # VCO_RESET_CALCODE (set by CBPro)
]
readback = bus.read_byte_data(IC_ADDR, OUT3_AMPL_ADDR) write_preamble(bus)
print(f"Si5340 OUTx_AMPL CLK3: 0x{readback}")
readback = bus.read_byte_data(IC_ADDR, OUT3_MUX_SEL_ADDR) time.sleep(0.3)
print(f"Si5340 OUTx_CM CLK3: 0x{readback}")
bus.write_byte_data( print("Writing main configuration...")
IC_ADDR, PAGE_ADDR, 0x3 for address, value in main_config:
) # setting page to 3 to change dividers values bus.write_byte_data(IC_ADDR, address, value)
print("Main configuration written")
n1_numerator = [0x0, 0x0, 0x0, 0x60, 0x22, 0x0] write_postamble(bus)
n1_numerator_10M = [0x0, 0x0, 0x0, 0xC0, 0x57, 0x1]
n1_num_addr = [0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12]
n1_denom_addr = [0x13, 0x14, 0x15, 0x16]
for addr, value in zip(n1_num_addr, n1_numerator):
bus.write_byte_data(IC_ADDR, addr, value)
bus.write_byte_data(IC_ADDR, N1_DIVIDER_UPDATE_ADDR, 1) if not wait_for_lock(bus):
print("Error waiting for input clock or PLL lock")
else:
print("Input clock present and PLL locked")
for addr in n1_num_addr: bus.write_byte_data(IC_ADDR, STATUS_STICKY, 0)
readback = bus.read_byte_data(IC_ADDR, addr)
print(f"Numerator buffer: 0x{readback:02x}")
for addr in n1_denom_addr: # Final status check
readback = bus.read_byte_data(IC_ADDR, addr) pll_locked = check_pll_status(bus)
print(f"Denominator buffer: 0x{readback:02x}") xaxb_signal_present = check_los_status(bus)
bus.write_byte_data(IC_ADDR, PAGE_ADDR, 0x0) # setting page to page 0 if not pll_locked:
print("Error: PLL is not locked")
elif not xaxb_signal_present:
print("Error: XA/XB signal is lost")
else:
print("Si5340 configuration completed successfully")
if __name__ == "__main__": if __name__ == "__main__":
configure_si5340() configure_si5340()

131
flake.nix
View File

@ -11,7 +11,7 @@
outputs = { self, nixpkgs, not-os, src-migen, src-misoc }: outputs = { self, nixpkgs, not-os, src-migen, src-misoc }:
let let
pkgs = import nixpkgs { system = "x86_64-linux"; overlays = [ crosspkgs-overlay ]; }; pkgs = import nixpkgs { system = "x86_64-linux"; overlays = [ crosspkgs-overlay ]; };
not-os-cfg = not-os-configured.config.system; pkgs-armv7l = pkgs.pkgsCross.zynq-armv7l-linux;
fsbl-support = ./fast-servo/fsbl-support; fsbl-support = ./fast-servo/fsbl-support;
patched-not-os = pkgs.applyPatches { patched-not-os = pkgs.applyPatches {
@ -27,6 +27,19 @@
]; ];
}; };
crossSystem = {
system = "armv7l-linux";
linux-kernel = {
name = "zynq";
baseConfig = "multi_v7_defconfig";
target = "uImage";
installTarget = "uImage";
autoModules = false;
DTB = true;
makeFlags = [ "LOADADDR=0x8000" ];
};
};
crosspkgs-overlay = (self: super: { crosspkgs-overlay = (self: super: {
pkgsCross = super.pkgsCross // { pkgsCross = super.pkgsCross // {
zynq-baremetal = import super.path { zynq-baremetal = import super.path {
@ -38,6 +51,10 @@
gcc.fpu = "vfpv3"; gcc.fpu = "vfpv3";
}; };
}; };
zynq-armv7l-linux = import super.path {
system = "x86_64-linux";
inherit crossSystem;
};
}; };
}); });
@ -83,38 +100,49 @@
runScript = "vivado"; runScript = "vivado";
}; };
pyrp3 = pkgs.python3Packages.buildPythonPackage rec { pyrp3 = pkgs-armv7l.python3Packages.buildPythonPackage rec {
pname = "pyrp3"; pname = "pyrp3";
version = "1.2.0"; version = "1.2.0";
pyproject = true; pyproject = true;
src = pkgs.fetchFromGitHub { src = pkgs.fetchFromGitHub {
owner = "linien-org"; owner = "linien-org";
repo = "${pname}"; repo = "pyrp3";
rev = "v${version}"; rev = "v${version}";
hash = "sha256-43TTlpJ5SMAjQM71bNVvrWQyciRXM3zpuA/Dw41AEgU="; hash = "sha256-43TTlpJ5SMAjQM71bNVvrWQyciRXM3zpuA/Dw41AEgU=";
}; };
nativeBuildInputs = with pkgs.python3Packages; [ setuptools wheel setuptools-scm ]; patches = ./fast-servo/linien-pyrp3-monitor.patch;
propagatedBuildInputs = with pkgs.python3Packages; [ nativeBuildInputs = with pkgs-armv7l.python3Packages; [
setuptools wheel setuptools-scm
] ++ (with pkgs-armv7l; [ gcc gnumake ]);
propagatedBuildInputs = with pkgs-armv7l.python3Packages; [
myhdl myhdl
rpyc4 rpyc4
cached-property cached-property
numpy numpy
]; ];
postInstall = ''
cp monitor/libmonitor.so $out/lib
'';
postFixup = ''
substituteInPlace $out/${pkgs.python3.sitePackages}/pyrp3/raw_memory.py \
--replace "libmonitor.so" "$out/lib/libmonitor.so"
'';
}; };
linien-server = pkgs.python3Packages.buildPythonPackage rec { linien-server = pkgs-armv7l.python3Packages.buildPythonPackage rec {
pname = "linien-server"; pname = "linien-server";
pyproject = true; pyproject = true;
inherit (pkgs.python3Packages.linien-common) src version; inherit (pkgs.python3Packages.linien-common) src version;
sourceRoot = "source/linien-server"; sourceRoot = "source/linien-server";
postPatch = '' postPatch = ''
cp ${fast-servo-gateware}/csrmap.py linien_server/csrmap.py
substituteInPlace linien_server/acquisition.py \ substituteInPlace linien_server/acquisition.py \
--replace " start_nginx()" "" \ --replace " start_nginx()" "" \
--replace " stop_nginx()" "" \ --replace " stop_nginx()" "" \
--replace " flash_fpga()" "" --replace " flash_fpga()" ""
''; '';
nativeBuildInputs = [ pkgs.python3Packages.setuptools ]; nativeBuildInputs = [ pkgs-armv7l.python3Packages.setuptools ];
propagatedBuildInputs = with pkgs.python3Packages; [ propagatedBuildInputs = with pkgs-armv7l.python3Packages; [
appdirs appdirs
certifi certifi
click click
@ -126,15 +154,6 @@
]; ];
}; };
not-os-configured = (import patched-not-os {
inherit nixpkgs;
extraModules = [
"${patched-not-os}/zynq_image.nix"
];
system = "x86_64-linux";
crossSystem.system = "armv7l-linux";
});
fast-servo-gateware = pkgs.stdenv.mkDerivation rec { fast-servo-gateware = pkgs.stdenv.mkDerivation rec {
name = "fast-servo-gateware"; name = "fast-servo-gateware";
inherit (pkgs.python3Packages.linien-common) src; inherit (pkgs.python3Packages.linien-common) src;
@ -167,11 +186,33 @@
mkdir -p $out $out/nix-support mkdir -p $out $out/nix-support
cp gateware/build/top.bit $out cp gateware/build/top.bit $out
cp linien-server/linien_server/gateware.bin $out cp linien-server/linien_server/gateware.bin $out
cp linien-server/linien_server/csrmap.py $out
echo file binary-dist $out/top.bit >> $out/nix-support/hydra-build-products echo file binary-dist $out/top.bit >> $out/nix-support/hydra-build-products
echo file binary-dist $out/gateware.bin >> $out/nix-support/hydra-build-products echo file binary-dist $out/gateware.bin >> $out/nix-support/hydra-build-products
''; '';
}; };
pyfastservo = pkgs-armv7l.python3Packages.buildPythonPackage rec {
name = "pyfastservo";
src = ./fast-servo;
preBuild = ''
cat > setup.py << EOF
from setuptools import setup
setup(
name="pyfastservo",
packages=["pyfastservo"],
install_requires=["spidev", "smbus2"],
entry_points = {"console_scripts": ["fp_leds=pyfastservo.fp_leds:main"]},
)
EOF
'';
propagatedBuildInputs = with pkgs-armv7l.python3Packages; [
spidev
smbus2
];
};
mkbootimage = pkgs.stdenv.mkDerivation { mkbootimage = pkgs.stdenv.mkDerivation {
pname = "mkbootimage"; pname = "mkbootimage";
version = "2.3dev"; version = "2.3dev";
@ -196,6 +237,37 @@
}; };
board-package-set = { board }: let board-package-set = { board }: let
not-os-configured = (import patched-not-os {
inherit nixpkgs;
extraModules = [
"${patched-not-os}/zynq_image.nix"
] ++ pkgs.lib.optionals (board == "fast-servo") [
({ config, pkgs, lib, ... }: {
environment.systemPackages = [
linien-server
(pkgs.python3.withPackages(ps: [ pyfastservo ]))
];
boot.postBootCommands = lib.mkAfter ''
# Program the FPGA
set +x
echo "Loading bitstream into SRAM..."
echo 0 > /sys/class/fpga_manager/fpga0/flags
mkdir -p /lib/firmware
cp ${fast-servo-gateware}/gateware.bin /lib/firmware/
echo gateware.bin > /sys/class/fpga_manager/fpga0/firmware
# Run device init scripts
echo "Initializing clock generator, ADC, and DAC..."
python3 -m pyfastservo.initialize
'';
})];
system = "x86_64-linux";
inherit crossSystem;
});
not-os-build = not-os-configured.config.system.build;
fsbl = pkgs.stdenv.mkDerivation { fsbl = pkgs.stdenv.mkDerivation {
name = "${board}-fsbl"; name = "${board}-fsbl";
src = pkgs.fetchFromGitHub { src = pkgs.fetchFromGitHub {
@ -234,9 +306,8 @@
dontFixup = true; dontFixup = true;
}; };
u-boot = let u-boot = (pkgs-armv7l.buildUBoot {
fast-servo-dts = fast-servo/fast-servo.dts; name = "${board}-u-boot";
in (pkgs.pkgsCross.armv7l-hf-multiplatform.buildUBoot {
defconfig = "xilinx_zynq_virt_defconfig"; defconfig = "xilinx_zynq_virt_defconfig";
patches = [] ++ pkgs.lib.optional (board == "fast-servo") ./fast-servo/u-boot.patch; patches = [] ++ pkgs.lib.optional (board == "fast-servo") ./fast-servo/u-boot.patch;
preConfigure = '' preConfigure = ''
@ -246,7 +317,7 @@
CONFIG_SYS_PROMPT="${board}-boot> " CONFIG_SYS_PROMPT="${board}-boot> "
CONFIG_AUTOBOOT=y CONFIG_AUTOBOOT=y
CONFIG_BOOTCOMMAND="${builtins.replaceStrings [ "\n" ] [ "; " ] '' CONFIG_BOOTCOMMAND="${builtins.replaceStrings [ "\n" ] [ "; " ] ''
setenv bootargs 'root=/dev/mmcblk0p2 console=ttyPS0,115200n8 systemConfig=${builtins.unsafeDiscardStringContext not-os-cfg.build.toplevel}' setenv bootargs 'root=/dev/mmcblk0p2 console=ttyPS0,115200n8 systemConfig=${builtins.unsafeDiscardStringContext not-os-build.toplevel}'
fatload mmc 0 0x6400000 uImage fatload mmc 0 0x6400000 uImage
fatload mmc 0 0x8000000 ${board}.dtb fatload mmc 0 0x8000000 ${board}.dtb
fatload mmc 0 0xA400000 uRamdisk.image.gz fatload mmc 0 0xA400000 uRamdisk.image.gz
@ -259,7 +330,7 @@
filesToInstall = [ "u-boot.elf" ]; filesToInstall = [ "u-boot.elf" ];
}).overrideAttrs (oldAttrs: { }).overrideAttrs (oldAttrs: {
postUnpack = '' postUnpack = ''
cp ${fast-servo-dts} $sourceRoot/arch/arm/dts/zynq-fast-servo.dts cp ${fast-servo/fast-servo.dts} $sourceRoot/arch/arm/dts/zynq-fast-servo.dts
''; '';
postInstall = '' postInstall = ''
mkdir -p $out/dts mkdir -p $out/dts
@ -290,7 +361,7 @@
echo file binary-dist $out/boot.bin >> $out/nix-support/hydra-build-products echo file binary-dist $out/boot.bin >> $out/nix-support/hydra-build-products
''; '';
dtb = pkgs.runCommand "dtb" dtb = pkgs.runCommand "${board}-dtb"
{ {
buildInputs = [ pkgs.gcc pkgs.dtc ]; buildInputs = [ pkgs.gcc pkgs.dtc ];
} }
@ -310,14 +381,14 @@
sd-image = let sd-image = let
rootfsImage = pkgs.callPackage (pkgs.path + "/nixos/lib/make-ext4-fs.nix") { rootfsImage = pkgs.callPackage (pkgs.path + "/nixos/lib/make-ext4-fs.nix") {
storePaths = [ not-os-cfg.build.toplevel ]; storePaths = [ not-os-build.toplevel ];
volumeLabel = "ROOT"; volumeLabel = "ROOT";
}; };
# Current firmware (kernel, bootimage, etc..) takes ~18MB # Current firmware (kernel, bootimage, etc..) takes ~18MB
firmwareSize = 30; firmwareSize = 30;
firmwarePartitionOffset = 8; firmwarePartitionOffset = 8;
in pkgs.stdenv.mkDerivation { in pkgs.stdenv.mkDerivation {
name = "sd-image"; name = "${board}-sd-image";
nativeBuildInputs = with pkgs; [ dosfstools mtools libfaketime util-linux parted ]; nativeBuildInputs = with pkgs; [ dosfstools mtools libfaketime util-linux parted ];
buildCommand = '' buildCommand = ''
mkdir -p $out/nix-support $out/sd-image mkdir -p $out/nix-support $out/sd-image
@ -351,8 +422,8 @@
mkdir firmware mkdir firmware
cp ${bootimage}/boot.bin firmware/ cp ${bootimage}/boot.bin firmware/
cp ${dtb}/${board}.dtb firmware/ cp ${dtb}/${board}.dtb firmware/
cp ${not-os-cfg.build.kernel}/uImage firmware/ cp ${not-os-build.kernel}/uImage firmware/
cp ${not-os-cfg.build.uRamdisk}/initrd firmware/uRamdisk.image.gz cp ${not-os-build.uRamdisk}/initrd firmware/uRamdisk.image.gz
(cd firmware; mcopy -psvm -i ../firmware_part.img ./* ::) (cd firmware; mcopy -psvm -i ../firmware_part.img ./* ::)
dd conv=notrunc if=firmware_part.img of=$img seek=$START count=$SECTORS dd conv=notrunc if=firmware_part.img of=$img seek=$START count=$SECTORS
@ -365,7 +436,9 @@
export PATH=${pkgs.qemu}/bin:$PATH export PATH=${pkgs.qemu}/bin:$PATH
IMGDIR=$(mktemp -d /tmp/not-os-qemu-XXXXXX) IMGDIR=$(mktemp -d /tmp/not-os-qemu-XXXXXX)
BASE=$(realpath $(dirname $0)) BASE=$(realpath $(dirname $0))
qemu-img create -F raw -f qcow2 -b $BASE/sd-image.img $IMGDIR/sd-overlay.qcow2 512M
qemu-img convert -O qcow2 -f raw -o preallocation=metadata $BASE/sd-image.img $IMGDIR/sd-sparse.qcow2
qemu-img create -F qcow2 -f qcow2 -b $IMGDIR/sd-sparse.qcow2 $IMGDIR/sd-overlay.qcow2 2G
# Some command arguments are based from samples in Xilinx QEMU User Documentation # Some command arguments are based from samples in Xilinx QEMU User Documentation
# See: https://xilinx-wiki.atlassian.net/wiki/spaces/A/pages/821854273/Running+Bare+Metal+Applications+on+QEMU # See: https://xilinx-wiki.atlassian.net/wiki/spaces/A/pages/821854273/Running+Bare+Metal+Applications+on+QEMU
@ -380,7 +453,7 @@
rm -rf $IMGDIR rm -rf $IMGDIR
''; '';
in pkgs.runCommand "not-os-qemu" { in pkgs.runCommand "${board}-qemu" {
inherit qemuScript; inherit qemuScript;
passAsFile = [ "qemuScript" ]; passAsFile = [ "qemuScript" ];
preferLocalBuild = true; preferLocalBuild = true;

View File

@ -151,10 +151,10 @@ index c61f9d6..fbdf0fd 100644
}; };
} }
diff --git a/zynq_image.nix b/zynq_image.nix diff --git a/zynq_image.nix b/zynq_image.nix
index 3fa23ab..e2e3871 100644 index 3fa23ab..9d1621e 100644
--- a/zynq_image.nix --- a/zynq_image.nix
+++ b/zynq_image.nix +++ b/zynq_image.nix
@@ -1,66 +1,102 @@ @@ -1,66 +1,89 @@
-{ config, pkgs, ... }: -{ config, pkgs, ... }:
+{ lib, config, pkgs, ... }: +{ lib, config, pkgs, ... }:
@ -163,22 +163,7 @@ index 3fa23ab..e2e3871 100644
- # dont use overlays for the qemu, it causes a lot of wasted time on recompiles - # dont use overlays for the qemu, it causes a lot of wasted time on recompiles
- x86pkgs = import pkgs.path { system = "x86_64-linux"; }; - x86pkgs = import pkgs.path { system = "x86_64-linux"; };
- customKernel = pkgs.linux.override { - customKernel = pkgs.linux.override {
+ crosspkgs = import pkgs.path { + customKernel = (pkgs.linux.override {
+ system = "x86_64-linux";
+ crossSystem = {
+ system = "armv7l-linux";
+ linux-kernel = {
+ name = "zynq";
+ baseConfig = "multi_v7_defconfig";
+ target = "uImage";
+ installTarget = "uImage";
+ autoModules = false;
+ DTB = true;
+ makeFlags = [ "LOADADDR=0x8000" ];
+ };
+ };
+ };
+ customKernel = (crosspkgs.linux.override {
extraConfig = '' extraConfig = ''
OVERLAY_FS y OVERLAY_FS y
+ MEDIA_SUPPORT n + MEDIA_SUPPORT n
@ -195,14 +180,15 @@ index 3fa23ab..e2e3871 100644
+ OF_OVERLAY y + OF_OVERLAY y
''; '';
- }; - };
- customKernelPackages = pkgs.linuxPackagesFor customKernel;
+ }).overrideAttrs (oa: { + }).overrideAttrs (oa: {
+ postInstall = '' + postInstall = ''
+ cp arch/arm/boot/uImage $out + if [ -e arch/arm/boot/uImage ]; then
+ cp arch/arm/boot/uImage $out
+ fi
+ ${oa.postInstall} + ${oa.postInstall}
+ ''; + '';
+ }); + });
+ customKernelPackages = crosspkgs.linuxPackagesFor customKernel; customKernelPackages = pkgs.linuxPackagesFor customKernel;
in { in {
imports = [ ./arm32-cross-fixes.nix ]; imports = [ ./arm32-cross-fixes.nix ];
boot.kernelPackages = customKernelPackages; boot.kernelPackages = customKernelPackages;
@ -253,12 +239,12 @@ index 3fa23ab..e2e3871 100644
- chmod +x qemu-script - chmod +x qemu-script
- patchShebangs qemu-script - patchShebangs qemu-script
- ls -ltrh - ls -ltrh
''; - '';
- system.build.rpi_image_tar = pkgs.runCommand "dist.tar" {} '' - system.build.rpi_image_tar = pkgs.runCommand "dist.tar" {} ''
- mkdir -p $out/nix-support - mkdir -p $out/nix-support
- tar -cvf $out/dist.tar ${config.system.build.rpi_image} - tar -cvf $out/dist.tar ${config.system.build.rpi_image}
- echo "file binary-dist $out/dist.tar" >> $out/nix-support/hydra-build-products - echo "file binary-dist $out/dist.tar" >> $out/nix-support/hydra-build-products
- ''; '';
- environment.systemPackages = [ pkgs.strace ]; - environment.systemPackages = [ pkgs.strace ];
- environment.etc."service/getty/run".source = pkgs.writeShellScript "getty" '' - environment.etc."service/getty/run".source = pkgs.writeShellScript "getty" ''
- agetty ttyPS0 115200 - agetty ttyPS0 115200

View File

@ -1062,13 +1062,13 @@ index 0000000..59aa585
++ ++
+ #endif /*_LINUX_FPGA_MGR_H */ + #endif /*_LINUX_FPGA_MGR_H */
diff --git a/zynq_image.nix b/zynq_image.nix diff --git a/zynq_image.nix b/zynq_image.nix
index e2e3871..2decd54 100644 index 9d1621e..012e50c 100644
--- a/zynq_image.nix --- a/zynq_image.nix
+++ b/zynq_image.nix +++ b/zynq_image.nix
@@ -18,6 +18,16 @@ let @@ -3,6 +3,16 @@
}; with lib;
}; let
customKernel = (crosspkgs.linux.override { customKernel = (pkgs.linux.override {
+ kernelPatches = [ + kernelPatches = [
+ ({ + ({
+ name = "xilinx-configfs-overlays"; + name = "xilinx-configfs-overlays";
@ -1082,7 +1082,7 @@ index e2e3871..2decd54 100644
extraConfig = '' extraConfig = ''
OVERLAY_FS y OVERLAY_FS y
MEDIA_SUPPORT n MEDIA_SUPPORT n
@@ -32,6 +42,7 @@ let @@ -17,6 +27,7 @@ let
OF_FPGA_REGION y OF_FPGA_REGION y
FPGA_MGR_ZYNQ_FPGA y FPGA_MGR_ZYNQ_FPGA y
OF_OVERLAY y OF_OVERLAY y