Compare commits
No commits in common. "master" and "spidev" have entirely different histories.
21
README.md
21
README.md
@ -1,21 +0,0 @@
|
|||||||
# Firmware for the Sinara 8462 Fast-Servo
|
|
||||||
## Building
|
|
||||||
### Reproducible build with Nix
|
|
||||||
1. Run `nix build .#packages.armv7l-linux.fast-servo-sd-image` to build the sd card image.
|
|
||||||
2. Run `nix develop` to build a dev shell to access the GUI.
|
|
||||||
|
|
||||||
### Flashing
|
|
||||||
1. Plug in your SD card to your computer and run `lsblk` to locate SD card
|
|
||||||
2. If there are any partitions on the SD card, run `umount <mount point>` all the related mount points.
|
|
||||||
3. Run `sudo dd if=<path to the SD Card Image> of=/dev/<SD Card Device Name in lsblk> bs=4M status=progress oflag=sync`
|
|
||||||
4. Eject the SD Card before removal
|
|
||||||
|
|
||||||
### Usage
|
|
||||||
1. Make sure the onboard DIP Switch is in the following condition.
|
|
||||||
- EN: OFF
|
|
||||||
- MODE: ON
|
|
||||||
2. Install the SD Card, power up the board via the power jack or PoE and plug in the RJ45 Ethernet cable.
|
|
||||||
3. Wait for all the front panel LEDs except the termination status LEDs to turn off. It can take a minutes or two for first boot. If it does not boot up, try to flash the SD Card again.
|
|
||||||
4. Run `ssh <fast servo ip address> -p 3030` to ssh into fast-servo and run `linien-server run` to start the linien server.
|
|
||||||
5. In the dev shell, run `linien` to launch the GUI. Add new device. Username is `root` and it does not take any password to log in. You leave the password field with any text.
|
|
||||||
6. Select the newly added device and click connect in the GUI to connect and start the GUI.
|
|
@ -1,66 +0,0 @@
|
|||||||
diff --git a/gateware/logic/autolock.py b/gateware/logic/autolock.py
|
|
||||||
index a6dc764..1a8407f 100644
|
|
||||||
--- a/gateware/logic/autolock.py
|
|
||||||
+++ b/gateware/logic/autolock.py
|
|
||||||
@@ -148,14 +148,17 @@ class RobustAutolock(Module, AutoCSR):
|
|
||||||
final_waited_for = Signal(bits_for(N_points))
|
|
||||||
|
|
||||||
# this is the signal that's used for detecting peaks
|
|
||||||
- sum_diff = Signal((len(self.sum_diff_calculator.output), True))
|
|
||||||
- abs_sum_diff = Signal.like(sum_diff)
|
|
||||||
+ self.sum_diff = Signal((len(self.sum_diff_calculator.output), True))
|
|
||||||
+ abs_sum_diff = Signal.like(self.sum_diff)
|
|
||||||
self.comb += [
|
|
||||||
self.sum_diff_calculator.writing_data_now.eq(self.writing_data_now),
|
|
||||||
self.sum_diff_calculator.restart.eq(self.at_start),
|
|
||||||
self.sum_diff_calculator.input.eq(self.input),
|
|
||||||
self.sum_diff_calculator.delay_value.eq(self.time_scale.storage),
|
|
||||||
- sum_diff.eq(self.sum_diff_calculator.output),
|
|
||||||
+ ]
|
|
||||||
+
|
|
||||||
+ self.sync += [
|
|
||||||
+ self.sum_diff.eq(self.sum_diff_calculator.output),
|
|
||||||
]
|
|
||||||
|
|
||||||
# has this signal at the moment the same sign as the peak we are looking for?
|
|
||||||
@@ -168,16 +171,17 @@ class RobustAutolock(Module, AutoCSR):
|
|
||||||
all_instructions_triggered = Signal()
|
|
||||||
|
|
||||||
self.comb += [
|
|
||||||
- sign_equal.eq((sum_diff > 0) == (current_peak_height > 0)),
|
|
||||||
- If(sum_diff >= 0, abs_sum_diff.eq(sum_diff)).Else(
|
|
||||||
- abs_sum_diff.eq(-1 * sum_diff)
|
|
||||||
+ sign_equal.eq((self.sum_diff > 0) == (current_peak_height > 0)),
|
|
||||||
+ If(self.sum_diff >= 0, abs_sum_diff.eq(self.sum_diff)).Else(
|
|
||||||
+ abs_sum_diff.eq(-1 * self.sum_diff)
|
|
||||||
),
|
|
||||||
If(
|
|
||||||
current_peak_height >= 0,
|
|
||||||
abs_current_peak_height.eq(current_peak_height),
|
|
||||||
).Else(abs_current_peak_height.eq(-1 * current_peak_height)),
|
|
||||||
over_threshold.eq(abs_sum_diff >= abs_current_peak_height),
|
|
||||||
- waited_long_enough.eq(waited_for > current_wait_for),
|
|
||||||
+ # HACK: To compensate the lock position output for the pipeline delay
|
|
||||||
+ waited_long_enough.eq((waited_for >= current_wait_for - 1) & (waited_for != 2 ** bits_for(N_points) - 1) & (current_wait_for - 1 != 2 ** bits_for(N_points) - 1)),
|
|
||||||
all_instructions_triggered.eq(
|
|
||||||
self.current_instruction_idx >= self.N_instructions.storage
|
|
||||||
),
|
|
||||||
@@ -190,7 +194,7 @@ class RobustAutolock(Module, AutoCSR):
|
|
||||||
self.sync += [
|
|
||||||
If(
|
|
||||||
self.at_start,
|
|
||||||
- waited_for.eq(0),
|
|
||||||
+ waited_for.eq(-1),
|
|
||||||
# fpga robust autolock algorithm registeres trigger events delayed.
|
|
||||||
# Therefore, we give it a head start for `final_waited_for`
|
|
||||||
final_waited_for.eq(ROBUST_AUTOLOCK_FPGA_DELAY),
|
|
||||||
@@ -213,7 +217,8 @@ class RobustAutolock(Module, AutoCSR):
|
|
||||||
self.current_instruction_idx.eq(
|
|
||||||
self.current_instruction_idx + 1
|
|
||||||
),
|
|
||||||
- waited_for.eq(0),
|
|
||||||
+ # HACK: To compensate the lock position output for the pipeline delay
|
|
||||||
+ waited_for.eq(-1),
|
|
||||||
).Else(waited_for.eq(waited_for + 1)),
|
|
||||||
),
|
|
||||||
If(
|
|
@ -1,13 +0,0 @@
|
|||||||
diff --git a/gateware/logic/iir.py b/gateware/logic/iir.py
|
|
||||||
index 2380dd7..60bfeb7 100644
|
|
||||||
--- a/gateware/logic/iir.py
|
|
||||||
+++ b/gateware/logic/iir.py
|
|
||||||
@@ -89,7 +89,7 @@ class Iir(Filter):
|
|
||||||
zr = Signal.like(z)
|
|
||||||
self.sync += zr.eq(z)
|
|
||||||
z = Signal.like(zr)
|
|
||||||
- self.comb += z.eq(zr + signal * c[coeff])
|
|
||||||
+ self.sync += z.eq(zr + signal * c[coeff])
|
|
||||||
self.comb += y_next.eq(z)
|
|
||||||
self.latency.value = Constant(order + 1)
|
|
||||||
self.interval.value = Constant(1)
|
|
@ -1,31 +0,0 @@
|
|||||||
diff --git a/linien-client/linien_client/deploy.py b/linien-client/linien_client/deploy.py
|
|
||||||
index df6683f..7355cc3 100644
|
|
||||||
--- a/linien-client/linien_client/deploy.py
|
|
||||||
+++ b/linien-client/linien_client/deploy.py
|
|
||||||
@@ -34,7 +34,7 @@ logger.setLevel(logging.DEBUG)
|
|
||||||
|
|
||||||
|
|
||||||
def read_remote_version(
|
|
||||||
- device: Device, ssh_port: int = 22, out_stream=sys.stdout
|
|
||||||
+ device: Device, ssh_port: int = 3030, out_stream=sys.stdout
|
|
||||||
) -> str:
|
|
||||||
"""Read the remote version of linien."""
|
|
||||||
|
|
||||||
@@ -62,7 +62,7 @@ def read_remote_version(
|
|
||||||
|
|
||||||
|
|
||||||
def start_remote_server(
|
|
||||||
- device: Device, ssh_port: int = 22, out_stream=sys.stdout
|
|
||||||
+ device: Device, ssh_port: int = 3030, out_stream=sys.stdout
|
|
||||||
) -> None:
|
|
||||||
"""Start the remote linien server."""
|
|
||||||
|
|
||||||
@@ -102,7 +102,7 @@ def start_remote_server(
|
|
||||||
|
|
||||||
|
|
||||||
def install_remote_server(
|
|
||||||
- device: Device, ssh_port: int = 22, out_stream=sys.stdout
|
|
||||||
+ device: Device, ssh_port: int = 3030, out_stream=sys.stdout
|
|
||||||
) -> None:
|
|
||||||
"""Install the remote linien server."""
|
|
||||||
|
|
@ -1,15 +0,0 @@
|
|||||||
diff --git a/linien-common/linien_common/common.py b/linien-common/linien_common/common.py
|
|
||||||
index 854d776..a310dbe 100644
|
|
||||||
--- a/linien-common/linien_common/common.py
|
|
||||||
+++ b/linien-common/linien_common/common.py
|
|
||||||
@@ -25,8 +25,8 @@ from typing import Dict, Iterable, List, Tuple, Union
|
|
||||||
import numpy as np
|
|
||||||
from scipy.signal import correlate, resample
|
|
||||||
|
|
||||||
-MHz = 0x10000000 / 8
|
|
||||||
-Vpp = ((1 << 14) - 1) / 4
|
|
||||||
+MHz = 0x10000000 / 8 * 125 / 100
|
|
||||||
+Vpp = (1 << 14) * 0.5 / 0.425 - 1
|
|
||||||
# conversion of bits to V
|
|
||||||
ANALOG_OUT_V = 1.8 / ((2**15) - 1)
|
|
||||||
|
|
38
fast-servo/linien-fast-servo-gateware.patch
Normal file
38
fast-servo/linien-fast-servo-gateware.patch
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
# diff from elhep/Fast-Servo-Firmmware commit ID 7fae40c:
|
||||||
|
# https://github.com/elhep/Fast-Servo-Firmware/commit/7fae40c0f872a91218be378f8289b98b1e366729
|
||||||
|
# Fix for migen add_source deprecation and removed xilinx bootgen command
|
||||||
|
# .bin file is being generated by bit2bin.py from Linien repository
|
||||||
|
# https://github.com/linien-org/linien/blob/master/gateware/bit2bin.py
|
||||||
|
|
||||||
|
diff --git a/fast_servo/gateware/fast_servo_platform.py b/fast_servo/gateware/fast_servo_platform.py
|
||||||
|
index 13b4aa3..89a8103 100644
|
||||||
|
--- a/fast_servo/gateware/fast_servo_platform.py
|
||||||
|
+++ b/fast_servo/gateware/fast_servo_platform.py
|
||||||
|
@@ -324,7 +324,12 @@ class Platform(XilinxPlatform):
|
||||||
|
self.ps7_config = ps7_config
|
||||||
|
|
||||||
|
verilog_sources = os.listdir(verilog_dir)
|
||||||
|
- self.add_sources(verilog_dir, *verilog_sources)
|
||||||
|
+ self.add_source_dir(verilog_dir)
|
||||||
|
+
|
||||||
|
+ def build(self, *args, **kwargs):
|
||||||
|
+ build_dir = kwargs.get('build_dir', 'build')
|
||||||
|
+ self.copy_sources(build_dir)
|
||||||
|
+ super().build(*args, **kwargs)
|
||||||
|
|
||||||
|
def do_finalize(self, fragment):
|
||||||
|
try:
|
||||||
|
diff --git a/fast_servo/gateware/fast_servo_soc.py b/fast_servo/gateware/fast_servo_soc.py
|
||||||
|
index 02128f5..abfc583 100644
|
||||||
|
--- a/fast_servo/gateware/fast_servo_soc.py
|
||||||
|
+++ b/fast_servo/gateware/fast_servo_soc.py
|
||||||
|
@@ -282,9 +282,3 @@ if __name__ == "__main__":
|
||||||
|
os.chdir(os.path.join(root_path, build_dir))
|
||||||
|
with open(f"{build_name}.bif", "w") as f:
|
||||||
|
f.write(f"all:\n{{\n\t{build_name}.bit\n}}")
|
||||||
|
-
|
||||||
|
- cmd = f"bootgen -image {build_name}.bif -arch zynq -process_bitstream bin -w on".split(" ")
|
||||||
|
- subprocess.run(cmd)
|
||||||
|
-
|
||||||
|
-
|
||||||
|
-
|
@ -1,42 +1,3 @@
|
|||||||
# diff from elhep/Fast-Servo-Firmmware commit ID 7fae40c:
|
|
||||||
# https://github.com/elhep/Fast-Servo-Firmware/commit/7fae40c0f872a91218be378f8289b98b1e366729
|
|
||||||
# Fix for migen add_source deprecation and removed xilinx bootgen command
|
|
||||||
# .bin file is being generated by bit2bin.py from Linien repository
|
|
||||||
# https://github.com/linien-org/linien/blob/master/gateware/bit2bin.py
|
|
||||||
|
|
||||||
diff --git a/fast_servo/gateware/fast_servo_platform.py b/fast_servo/gateware/fast_servo_platform.py
|
|
||||||
index 13b4aa3..89a8103 100644
|
|
||||||
--- a/fast_servo/gateware/fast_servo_platform.py
|
|
||||||
+++ b/fast_servo/gateware/fast_servo_platform.py
|
|
||||||
@@ -324,7 +324,12 @@ class Platform(XilinxPlatform):
|
|
||||||
self.ps7_config = ps7_config
|
|
||||||
|
|
||||||
verilog_sources = os.listdir(verilog_dir)
|
|
||||||
- self.add_sources(verilog_dir, *verilog_sources)
|
|
||||||
+ self.add_source_dir(verilog_dir)
|
|
||||||
+
|
|
||||||
+ def build(self, *args, **kwargs):
|
|
||||||
+ build_dir = kwargs.get('build_dir', 'build')
|
|
||||||
+ self.copy_sources(build_dir)
|
|
||||||
+ super().build(*args, **kwargs)
|
|
||||||
|
|
||||||
def do_finalize(self, fragment):
|
|
||||||
try:
|
|
||||||
diff --git a/fast_servo/gateware/fast_servo_soc.py b/fast_servo/gateware/fast_servo_soc.py
|
|
||||||
index 02128f5..abfc583 100644
|
|
||||||
--- a/fast_servo/gateware/fast_servo_soc.py
|
|
||||||
+++ b/fast_servo/gateware/fast_servo_soc.py
|
|
||||||
@@ -282,9 +282,3 @@ if __name__ == "__main__":
|
|
||||||
os.chdir(os.path.join(root_path, build_dir))
|
|
||||||
with open(f"{build_name}.bif", "w") as f:
|
|
||||||
f.write(f"all:\n{{\n\t{build_name}.bit\n}}")
|
|
||||||
-
|
|
||||||
- cmd = f"bootgen -image {build_name}.bif -arch zynq -process_bitstream bin -w on".split(" ")
|
|
||||||
- subprocess.run(cmd)
|
|
||||||
-
|
|
||||||
-
|
|
||||||
-
|
|
||||||
|
|
||||||
# diff between linen-org/linien commit ID 93f1f50:
|
# diff between linen-org/linien commit ID 93f1f50:
|
||||||
# https://github.com/linien-org/linien/commit/93f1f50ebd86fe3314cab5a549462d0fcbf6a658
|
# https://github.com/linien-org/linien/commit/93f1f50ebd86fe3314cab5a549462d0fcbf6a658
|
||||||
# and elhep/linien commit ID b73eea0:
|
# and elhep/linien commit ID b73eea0:
|
||||||
@ -55,27 +16,41 @@ index b3f3683..98c6e51 100644
|
|||||||
|
|
||||||
- repo: https://github.com/pycqa/isort
|
- repo: https://github.com/pycqa/isort
|
||||||
rev: 5.12.0
|
rev: 5.12.0
|
||||||
|
diff --git a/gateware/build_fpga_image.sh b/gateware/build_fpga_image.sh
|
||||||
|
index f822402..be7401c 100644
|
||||||
|
--- a/gateware/build_fpga_image.sh
|
||||||
|
+++ b/gateware/build_fpga_image.sh
|
||||||
|
@@ -16,4 +16,9 @@ export PATH=$VIVADOPATH:$PATH
|
||||||
|
|
||||||
|
rm linien-server/linien_server/gateware.bin -f
|
||||||
|
# run with -m option to avoid errors related to relative imports without breaking pytest
|
||||||
|
-python3 -m gateware.fpga_image_helper
|
||||||
|
\ No newline at end of file
|
||||||
|
+
|
||||||
|
+if [ -z "$1" ]; then
|
||||||
|
+ python3 -m gateware.fpga_image_helper
|
||||||
|
+else
|
||||||
|
+ python3 -m gateware.fpga_image_helper -p $1
|
||||||
|
+fi
|
||||||
|
\ No newline at end of file
|
||||||
diff --git a/gateware/fpga_image_helper.py b/gateware/fpga_image_helper.py
|
diff --git a/gateware/fpga_image_helper.py b/gateware/fpga_image_helper.py
|
||||||
index c3e20e7..ebead1d 100644
|
index 6c34429..a0b12d0 100644
|
||||||
--- a/gateware/fpga_image_helper.py
|
--- a/gateware/fpga_image_helper.py
|
||||||
+++ b/gateware/fpga_image_helper.py
|
+++ b/gateware/fpga_image_helper.py
|
||||||
@@ -1,6 +1,7 @@
|
@@ -1,5 +1,6 @@
|
||||||
# This file is part of Linien and based on redpid.
|
# Copyright 2014-2015 Robert Jördens <jordens@gmail.com>
|
||||||
#
|
# Copyright 2018-2022 Benjamin Wiegand <benjamin.wiegand@physik.hu-berlin.de>
|
||||||
# Copyright (C) 2016-2024 Linien Authors (https://github.com/linien-org/linien#license)
|
|
||||||
+# Copyright 2023 Jakub Matyas <jakubk.m@gmail.com>
|
+# Copyright 2023 Jakub Matyas <jakubk.m@gmail.com>
|
||||||
#
|
#
|
||||||
# Linien is free software: you can redistribute it and/or modify
|
# This file is part of Linien and based on redpid.
|
||||||
# it under the terms of the GNU General Public License as published by
|
#
|
||||||
@@ -20,16 +21,18 @@
|
@@ -23,14 +24,16 @@ from pathlib import Path
|
||||||
from pathlib import Path
|
REPO_ROOT_DIR = Path(__file__).resolve().parents[1]
|
||||||
|
|
||||||
from .bit2bin import bit2bin
|
from .bit2bin import bit2bin
|
||||||
-from .hw_platform import Platform
|
-from .hw_platform import Platform
|
||||||
-from .linien_module import RootModule
|
-from .linien_module import RootModule
|
||||||
|
|
||||||
REPO_ROOT_DIR = Path(__file__).resolve().parents[1]
|
|
||||||
|
|
||||||
|
|
||||||
def py_csrconstants(map, fil):
|
def py_csrconstants(map, fil):
|
||||||
fil.write("csr_constants = {\n")
|
fil.write("csr_constants = {\n")
|
||||||
@ -90,7 +65,7 @@ index c3e20e7..ebead1d 100644
|
|||||||
fil.write("}\n\n")
|
fil.write("}\n\n")
|
||||||
|
|
||||||
|
|
||||||
@@ -51,26 +54,51 @@ def get_csrmap(banks):
|
@@ -52,26 +55,49 @@ def get_csrmap(banks):
|
||||||
def py_csrmap(it, fil):
|
def py_csrmap(it, fil):
|
||||||
fil.write("csr = {\n")
|
fil.write("csr = {\n")
|
||||||
for reg in it:
|
for reg in it:
|
||||||
@ -109,7 +84,7 @@ index c3e20e7..ebead1d 100644
|
|||||||
- platform = Platform()
|
- platform = Platform()
|
||||||
- root = RootModule(platform)
|
- root = RootModule(platform)
|
||||||
+ import argparse
|
+ import argparse
|
||||||
+
|
|
||||||
+ parser = argparse.ArgumentParser()
|
+ parser = argparse.ArgumentParser()
|
||||||
+ parser.add_argument("-p", "--platform", default=None)
|
+ parser.add_argument("-p", "--platform", default=None)
|
||||||
+ args = parser.parse_args()
|
+ args = parser.parse_args()
|
||||||
@ -128,11 +103,10 @@ index c3e20e7..ebead1d 100644
|
|||||||
+ root = LinienFastServo(platform)
|
+ root = LinienFastServo(platform)
|
||||||
+ else:
|
+ else:
|
||||||
+ raise ValueError("Unknown platform")
|
+ raise ValueError("Unknown platform")
|
||||||
+
|
+
|
||||||
+ platform.add_source_dir(REPO_ROOT_DIR / "gateware" / "verilog")
|
+ platform.add_source_dir(REPO_ROOT_DIR / "gateware" / "verilog")
|
||||||
+ build_dir = REPO_ROOT_DIR / "gateware" / "build"
|
+ build_dir = REPO_ROOT_DIR / "gateware" / "build"
|
||||||
+ platform.build(root, build_name="top", build_dir=build_dir, run=True)
|
+ platform.build(root, build_name="top", build_dir=build_dir, run=True)
|
||||||
|
|
||||||
with open(
|
with open(
|
||||||
REPO_ROOT_DIR / "linien-server" / "linien_server" / "csrmap.py", "w"
|
REPO_ROOT_DIR / "linien-server" / "linien_server" / "csrmap.py", "w"
|
||||||
) as fil:
|
) as fil:
|
||||||
@ -143,7 +117,7 @@ index c3e20e7..ebead1d 100644
|
|||||||
py_csrmap(csr, fil)
|
py_csrmap(csr, fil)
|
||||||
fil.write("states = {}\n".format(repr(root.linien.state_names)))
|
fil.write("states = {}\n".format(repr(root.linien.state_names)))
|
||||||
fil.write("signals = {}\n".format(repr(root.linien.signal_names)))
|
fil.write("signals = {}\n".format(repr(root.linien.signal_names)))
|
||||||
|
-
|
||||||
- platform.add_source_dir(REPO_ROOT_DIR / "gateware" / "verilog")
|
- platform.add_source_dir(REPO_ROOT_DIR / "gateware" / "verilog")
|
||||||
- build_dir = REPO_ROOT_DIR / "gateware" / "build"
|
- build_dir = REPO_ROOT_DIR / "gateware" / "build"
|
||||||
- platform.build(root, build_name="top", build_dir=build_dir)
|
- platform.build(root, build_name="top", build_dir=build_dir)
|
||||||
@ -154,14 +128,14 @@ diff --git a/gateware/linien_module.py b/gateware/linien_module.py
|
|||||||
index 16ca186..6905ac0 100644
|
index 16ca186..6905ac0 100644
|
||||||
--- a/gateware/linien_module.py
|
--- a/gateware/linien_module.py
|
||||||
+++ b/gateware/linien_module.py
|
+++ b/gateware/linien_module.py
|
||||||
@@ -1,6 +1,7 @@
|
@@ -2,6 +2,7 @@
|
||||||
# This file is part of Linien and based on redpid.
|
# Copyright 2018-2022 Benjamin Wiegand <benjamin.wiegand@physik.hu-berlin.de>
|
||||||
#
|
# Copyright 2021-2023 Bastian Leykauf <leykauf@physik.hu-berlin.de>
|
||||||
# Copyright (C) 2016-2024 Linien Authors (https://github.com/linien-org/linien#license)
|
# Copyright 2022 Christian Freier <christian.freier@nomadatomics.com>
|
||||||
+# Copyright 2023 Jakub Matyas <jakubk.m@gmail.com>
|
+# Copyright 2023 Jakub Matyas <jakubk.m@gmail.com>
|
||||||
#
|
#
|
||||||
# Linien is free software: you can redistribute it and/or modify
|
# This file is part of Linien and based on redpid.
|
||||||
# it under the terms of the GNU General Public License as published by
|
#
|
||||||
@@ -36,19 +37,13 @@ from misoc.interconnect.csr import AutoCSR, CSRStatus, CSRStorage
|
@@ -36,19 +37,13 @@ from misoc.interconnect.csr import AutoCSR, CSRStatus, CSRStorage
|
||||||
from .logic.autolock import FPGAAutolock
|
from .logic.autolock import FPGAAutolock
|
||||||
from .logic.chains import FastChain, SlowChain, cross_connect
|
from .logic.chains import FastChain, SlowChain, cross_connect
|
@ -20,15 +20,13 @@
|
|||||||
from migen import *
|
from migen import *
|
||||||
from migen.genlib.cdc import MultiReg
|
from migen.genlib.cdc import MultiReg
|
||||||
from misoc.interconnect.csr import AutoCSR, CSRStatus, CSRStorage
|
from misoc.interconnect.csr import AutoCSR, CSRStatus, CSRStorage
|
||||||
from misoc.interconnect.stream import AsyncFIFO
|
|
||||||
|
|
||||||
|
|
||||||
class CRG(Module):
|
class _CRG(Module):
|
||||||
def __init__(self, platform, dco_clk, dco_freq=200e6):
|
def __init__(self, platform, dco_clk, dco_freq=200e6):
|
||||||
self.clock_domains.cd_dco = ClockDomain()
|
self.clock_domains.cd_dco = ClockDomain()
|
||||||
self.clock_domains.cd_dco2x = ClockDomain()
|
self.clock_domains.cd_dco2x = ClockDomain()
|
||||||
self.clock_domains.cd_dco2d = ClockDomain()
|
self.clock_domains.cd_dco2d = ClockDomain()
|
||||||
self.clock_domains.cd_dco2d_45_degree = ClockDomain()
|
|
||||||
dco_clk_p, dco_clk_n = dco_clk
|
dco_clk_p, dco_clk_n = dco_clk
|
||||||
|
|
||||||
dco_clk_buf = Signal()
|
dco_clk_buf = Signal()
|
||||||
@ -43,83 +41,59 @@ class CRG(Module):
|
|||||||
clk_dco = Signal()
|
clk_dco = Signal()
|
||||||
clk_dco2x = Signal()
|
clk_dco2x = Signal()
|
||||||
clk_dco2d = Signal()
|
clk_dco2d = Signal()
|
||||||
clk_dco2d_45_degree = Signal()
|
|
||||||
mmcm_ps_psdone = Signal()
|
|
||||||
|
|
||||||
self.locked = Signal()
|
self.locked = Signal()
|
||||||
self.mmcm_rst = Signal()
|
|
||||||
self.ddr_clk_phase_shift_en = Signal()
|
|
||||||
self.ddr_clk_phase_incdec = Signal()
|
|
||||||
|
|
||||||
platform.add_period_constraint(dco_clk_p, 1e9 / dco_freq)
|
platform.add_period_constraint(dco_clk_p, 1e9 / dco_freq)
|
||||||
self.specials += [
|
self.specials += [
|
||||||
Instance(
|
Instance(
|
||||||
"MMCME2_ADV",
|
"PLLE2_BASE",
|
||||||
p_BANDWIDTH="OPTIMIZED",
|
p_BANDWIDTH="OPTIMIZED",
|
||||||
p_DIVCLK_DIVIDE=1,
|
p_DIVCLK_DIVIDE=1,
|
||||||
p_CLKFBOUT_PHASE=0.0,
|
p_CLKFBOUT_PHASE=0.0,
|
||||||
p_CLKFBOUT_MULT_F=4, # VCO @ 800 MHz
|
p_CLKFBOUT_MULT=4, # VCO @ 800 MHz
|
||||||
p_CLKIN1_PERIOD=(1e9 / dco_freq),
|
p_CLKIN1_PERIOD=(1e9 / dco_freq),
|
||||||
p_REF_JITTER1=0.01,
|
p_REF_JITTER1=0.01,
|
||||||
p_STARTUP_WAIT="FALSE",
|
p_STARTUP_WAIT="FALSE",
|
||||||
i_CLKIN1=dco_clk_buf,
|
i_CLKIN1=dco_clk_buf,
|
||||||
i_PWRDWN=0,
|
i_PWRDWN=0,
|
||||||
i_RST=ResetSignal("sys") | self.mmcm_rst,
|
i_RST=ResetSignal("sys"),
|
||||||
i_CLKFBIN=clk_feedback_buf,
|
i_CLKFBIN=clk_feedback_buf,
|
||||||
o_CLKFBOUT=clk_feedback,
|
o_CLKFBOUT=clk_feedback,
|
||||||
|
p_CLKOUT0_DIVIDE=4,
|
||||||
p_CLKOUT0_USE_FINE_PS="TRUE",
|
p_CLKOUT0_PHASE=0.0,
|
||||||
p_CLKOUT0_DIVIDE_F=8,
|
|
||||||
p_CLKOUT0_PHASE=45.0,
|
|
||||||
p_CLKOUT0_DUTY_CYCLE=0.5,
|
p_CLKOUT0_DUTY_CYCLE=0.5,
|
||||||
o_CLKOUT0=clk_dco2d_45_degree, # 100 MHz <- dco_clk / 2 = 200 MHz / 2
|
o_CLKOUT0=clk_dco, # 200 MHz <- dco_clk
|
||||||
o_LOCKED=self.locked,
|
|
||||||
|
|
||||||
p_CLKOUT1_DIVIDE=2,
|
p_CLKOUT1_DIVIDE=2,
|
||||||
p_CLKOUT1_PHASE=0.0,
|
p_CLKOUT1_PHASE=0.0,
|
||||||
p_CLKOUT1_DUTY_CYCLE=0.5,
|
p_CLKOUT1_DUTY_CYCLE=0.5,
|
||||||
o_CLKOUT1=clk_dco2x, # 400 MHZ <- 2 * dco_clk = 2*200 MHz
|
o_CLKOUT1=clk_dco2x, # 400 MHZ <- 2 * dco_clk = 2*200 MHz
|
||||||
|
|
||||||
p_CLKOUT2_DIVIDE=8,
|
p_CLKOUT2_DIVIDE=8,
|
||||||
p_CLKOUT2_PHASE=0.0,
|
p_CLKOUT2_PHASE=0.0,
|
||||||
p_CLKOUT2_DUTY_CYCLE=0.5,
|
p_CLKOUT2_DUTY_CYCLE=0.5,
|
||||||
o_CLKOUT2=clk_dco2d, # 100 MHz <- dco_clk / 2 = 200 MHz / 2
|
o_CLKOUT2=clk_dco2d, # 100 MHz <- dco_clk / 2 = 200 MHz / 2
|
||||||
|
o_LOCKED=self.locked,
|
||||||
p_CLKOUT3_DIVIDE=4,
|
|
||||||
p_CLKOUT3_PHASE=0.0,
|
|
||||||
p_CLKOUT3_DUTY_CYCLE=0.5,
|
|
||||||
o_CLKOUT3=clk_dco, # 200 MHz <- dco_clk
|
|
||||||
|
|
||||||
i_PSCLK=ClockSignal(),
|
|
||||||
i_PSEN=self.ddr_clk_phase_shift_en,
|
|
||||||
i_PSINCDEC=self.ddr_clk_phase_incdec,
|
|
||||||
o_PSDONE=mmcm_ps_psdone,
|
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
|
|
||||||
self.specials += Instance("BUFG", i_I=clk_feedback, o_O=clk_feedback_buf)
|
self.specials += Instance("BUFG", i_I=clk_feedback, o_O=clk_feedback_buf)
|
||||||
self.specials += Instance("BUFG", i_I=clk_dco, o_O=self.cd_dco.clk)
|
self.specials += Instance("BUFG", i_I=clk_dco, o_O=self.cd_dco.clk)
|
||||||
self.specials += Instance("BUFG", i_I=clk_dco2d, o_O=self.cd_dco2d.clk)
|
self.specials += Instance("BUFG", i_I=clk_dco2d, o_O=self.cd_dco2d.clk)
|
||||||
self.specials += Instance("BUFG", i_I=clk_dco2d_45_degree, o_O=self.cd_dco2d_45_degree.clk)
|
|
||||||
self.specials += Instance("BUFG", i_I=clk_dco2x, o_O=self.cd_dco2x.clk)
|
self.specials += Instance("BUFG", i_I=clk_dco2x, o_O=self.cd_dco2x.clk)
|
||||||
|
|
||||||
# Ignore dco2d to mmcm dco_clk path created by SoC's rst.
|
|
||||||
platform.add_false_path_constraints(self.cd_dco2d.clk, dco_clk_buf)
|
|
||||||
self.specials += Instance("FD", p_INIT=1, i_D=~self.locked, i_C=self.cd_dco2d.clk, o_Q=self.cd_dco2d.rst)
|
|
||||||
|
|
||||||
class ADC(Module, AutoCSR):
|
class ADC(Module, AutoCSR):
|
||||||
def __init__(self, platform, dco_freq=200e6):
|
def __init__(self, platform, dco_freq=200e6):
|
||||||
adc_pads = platform.request("adc")
|
adc_pads = platform.request("adc")
|
||||||
afe_pads = platform.request("adc_afe")
|
afe_pads = platform.request("adc_afe")
|
||||||
|
|
||||||
self.frame_csr = CSRStatus(5)
|
self.frame_csr = CSRStatus(4)
|
||||||
self.data_ch0 = CSRStatus(16)
|
self.data_ch0 = CSRStatus(16)
|
||||||
self.data_ch1 = CSRStatus(16)
|
self.data_ch1 = CSRStatus(16)
|
||||||
|
|
||||||
self.tap_delay = CSRStorage(5)
|
self.tap_delay = CSRStorage(5)
|
||||||
self.bitslip_csr = CSRStorage(1)
|
self.bitslip_csr = CSRStorage(1)
|
||||||
|
|
||||||
self.afe_ctrl = CSRStorage(7)
|
self.afe_ctrl = CSRStorage(4)
|
||||||
|
|
||||||
tap_delay_val = Signal(5)
|
tap_delay_val = Signal(5)
|
||||||
bitslip = Signal()
|
bitslip = Signal()
|
||||||
@ -131,17 +105,7 @@ class ADC(Module, AutoCSR):
|
|||||||
ch2_shdn = Signal()
|
ch2_shdn = Signal()
|
||||||
|
|
||||||
self.data_out = [Signal(16, reset_less=True), Signal(16, reset_less=True)]
|
self.data_out = [Signal(16, reset_less=True), Signal(16, reset_less=True)]
|
||||||
self.data_out_cdc = [Signal(16, reset_less=True), Signal(16, reset_less=True)]
|
|
||||||
self.s_frame = Signal(4)
|
self.s_frame = Signal(4)
|
||||||
self.s_frame_cdc = Signal(4)
|
|
||||||
|
|
||||||
self.submodules.cdc_fifo = ClockDomainsRenamer({"write": "dco2d", "read": "sys"})(AsyncFIFO([("data", 36)], 4))
|
|
||||||
self.comb += [
|
|
||||||
self.cdc_fifo.sink.data.eq(Cat(self.data_out_cdc[0], self.data_out_cdc[1], self.s_frame_cdc)),
|
|
||||||
self.cdc_fifo.sink.stb.eq(~ResetSignal("dco2d")),
|
|
||||||
Cat(self.data_out[0], self.data_out[1], self.s_frame).eq(self.cdc_fifo.source.data),
|
|
||||||
self.cdc_fifo.source.ack.eq(~ResetSignal("sys")),
|
|
||||||
]
|
|
||||||
|
|
||||||
###
|
###
|
||||||
|
|
||||||
@ -153,14 +117,11 @@ class ADC(Module, AutoCSR):
|
|||||||
# dco_clk.n.eq(adc_pads.dco_n),
|
# dco_clk.n.eq(adc_pads.dco_n),
|
||||||
tap_delay_val.eq(self.tap_delay.storage),
|
tap_delay_val.eq(self.tap_delay.storage),
|
||||||
Cat(ch1_gain_x10, ch2_gain_x10, ch1_shdn, ch2_shdn).eq(
|
Cat(ch1_gain_x10, ch2_gain_x10, ch1_shdn, ch2_shdn).eq(
|
||||||
self.afe_ctrl.storage[0:4]
|
self.afe_ctrl.storage
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|
||||||
self.submodules.crg = CRG(platform, dco_clk, dco_freq)
|
self.submodules._crg = _CRG(platform, dco_clk, dco_freq)
|
||||||
self.comb += self.afe_ctrl.storage[4].eq(self.crg.mmcm_rst)
|
|
||||||
self.comb += self.afe_ctrl.storage[5].eq(self.crg.ddr_clk_phase_shift_en)
|
|
||||||
self.comb += self.afe_ctrl.storage[6].eq(self.crg.ddr_clk_phase_incdec)
|
|
||||||
|
|
||||||
self.specials += MultiReg(self.bitslip_csr.re, bitslip_re_dco_2d, "dco2d")
|
self.specials += MultiReg(self.bitslip_csr.re, bitslip_re_dco_2d, "dco2d")
|
||||||
self.sync.dco2d += [
|
self.sync.dco2d += [
|
||||||
@ -168,8 +129,7 @@ class ADC(Module, AutoCSR):
|
|||||||
]
|
]
|
||||||
|
|
||||||
self.comb += [
|
self.comb += [
|
||||||
self.frame_csr.status[0:4].eq(self.s_frame[0:4]),
|
self.frame_csr.status.eq(self.s_frame),
|
||||||
self.frame_csr.status[4].eq(self.crg.locked),
|
|
||||||
self.data_ch0.status.eq(self.data_out[0]),
|
self.data_ch0.status.eq(self.data_out[0]),
|
||||||
self.data_ch1.status.eq(self.data_out[1]),
|
self.data_ch1.status.eq(self.data_out[1]),
|
||||||
]
|
]
|
||||||
@ -186,7 +146,7 @@ class ADC(Module, AutoCSR):
|
|||||||
|
|
||||||
self.specials += Instance(
|
self.specials += Instance(
|
||||||
"LTC2195",
|
"LTC2195",
|
||||||
i_rst_in=ResetSignal("dco2d"),
|
i_rst_in=ResetSignal("sys"),
|
||||||
i_clk200=ClockSignal("idelay"),
|
i_clk200=ClockSignal("idelay"),
|
||||||
i_DCO=ClockSignal("dco"),
|
i_DCO=ClockSignal("dco"),
|
||||||
i_DCO_2D=ClockSignal("dco2d"),
|
i_DCO_2D=ClockSignal("dco2d"),
|
||||||
@ -198,9 +158,9 @@ class ADC(Module, AutoCSR):
|
|||||||
i_D1_in_n=adc_pads.data1_n,
|
i_D1_in_n=adc_pads.data1_n,
|
||||||
i_bitslip=bitslip,
|
i_bitslip=bitslip,
|
||||||
i_delay_val=tap_delay_val,
|
i_delay_val=tap_delay_val,
|
||||||
o_ADC0_out=self.data_out_cdc[1], # LANES swapped on hardware
|
o_ADC0_out=self.data_out[1], # LANES swapped on hardware
|
||||||
o_ADC1_out=self.data_out_cdc[0],
|
o_ADC1_out=self.data_out[0],
|
||||||
o_FR_out=self.s_frame_cdc,
|
o_FR_out=self.s_frame,
|
||||||
o_o_data_from_pins=dummy,
|
o_o_data_from_pins=dummy,
|
||||||
o_idelay_rdy=dummy_idelay_rdy,
|
o_idelay_rdy=dummy_idelay_rdy,
|
||||||
)
|
)
|
||||||
|
@ -20,7 +20,6 @@
|
|||||||
from migen import *
|
from migen import *
|
||||||
from misoc.interconnect.csr import AutoCSR, CSRStorage
|
from misoc.interconnect.csr import AutoCSR, CSRStorage
|
||||||
from migen.genlib.io import DDROutput
|
from migen.genlib.io import DDROutput
|
||||||
from misoc.interconnect.stream import AsyncFIFO
|
|
||||||
|
|
||||||
|
|
||||||
class DAC(Module, AutoCSR):
|
class DAC(Module, AutoCSR):
|
||||||
@ -39,51 +38,37 @@ class DAC(Module, AutoCSR):
|
|||||||
output_data_ch1 = Signal(14)
|
output_data_ch1 = Signal(14)
|
||||||
|
|
||||||
self.data_in = [Signal(14, reset_less=True), Signal(14, reset_less=True)]
|
self.data_in = [Signal(14, reset_less=True), Signal(14, reset_less=True)]
|
||||||
self.data_in_csr = [Signal(14, reset_less=True), Signal(14, reset_less=True)]
|
|
||||||
|
|
||||||
self.data_in_cdc = [Signal(14, reset_less=True), Signal(14, reset_less=True)]
|
|
||||||
self.data_in_csr_cdc = [Signal(14, reset_less=True), Signal(14, reset_less=True)]
|
|
||||||
platform.add_period_constraint(dac_pads.dclkio, 10.0)
|
platform.add_period_constraint(dac_pads.dclkio, 10.0)
|
||||||
|
|
||||||
self.submodules.cdc_fifo = ClockDomainsRenamer({"write": "sys", "read": "dco2d"})(AsyncFIFO([("data", 56)], 4))
|
|
||||||
self.comb += [
|
|
||||||
self.data_in_csr[0].eq(self.output_value_ch0.storage),
|
|
||||||
self.data_in_csr[1].eq(self.output_value_ch1.storage),
|
|
||||||
self.cdc_fifo.sink.data.eq(Cat(self.data_in[0], self.data_in[1], self.data_in_csr[0], self.data_in_csr[1])),
|
|
||||||
self.cdc_fifo.sink.stb.eq(~ResetSignal("sys")),
|
|
||||||
Cat(self.data_in_cdc[0], self.data_in_cdc[1], self.data_in_csr_cdc[0], self.data_in_csr_cdc[1]).eq(self.cdc_fifo.source.data),
|
|
||||||
self.cdc_fifo.source.ack.eq(~ResetSignal("dco2d")),
|
|
||||||
]
|
|
||||||
|
|
||||||
self.comb += [
|
self.comb += [
|
||||||
Cat(manual_override, ch0_pd, ch1_pd).eq(self.dac_ctrl.storage),
|
Cat(manual_override, ch0_pd, ch1_pd).eq(self.dac_ctrl.storage),
|
||||||
dac_pads.rst.eq(ResetSignal("dco2d")),
|
dac_pads.rst.eq(ResetSignal("sys")),
|
||||||
dac_afe_pads.ch1_pd_n.eq(~ch0_pd),
|
dac_afe_pads.ch1_pd_n.eq(~ch0_pd),
|
||||||
dac_afe_pads.ch2_pd_n.eq(~ch1_pd),
|
dac_afe_pads.ch2_pd_n.eq(~ch1_pd),
|
||||||
output_data_ch0.eq(
|
output_data_ch0.eq(
|
||||||
Mux(manual_override, self.data_in_csr_cdc[0], self.data_in_cdc[0])
|
Mux(manual_override, self.output_value_ch0.storage, self.data_in[0])
|
||||||
),
|
),
|
||||||
output_data_ch1.eq(
|
output_data_ch1.eq(
|
||||||
Mux(manual_override, self.data_in_csr_cdc[1], self.data_in_cdc[1])
|
Mux(manual_override, self.output_value_ch1.storage, self.data_in[1])
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|
||||||
self.specials += [
|
# data
|
||||||
Instance("ODDR",
|
for lane in range(14):
|
||||||
i_C=ClockSignal("dco2d"),
|
self.specials += DDROutput(
|
||||||
i_CE=~ResetSignal("dco2d"),
|
i1 = output_data_ch0[lane],
|
||||||
i_D1=output_data_ch0[lane], # DDR CLK Rising Edge
|
i2 = output_data_ch1[lane],
|
||||||
i_D2=output_data_ch1[lane], # DDR CLK Falling Edge
|
o = dac_pads.data[lane],
|
||||||
o_Q=dac_pads.data[lane],
|
clk = ClockSignal("dco2d")
|
||||||
p_DDR_CLK_EDGE="SAME_EDGE")
|
)
|
||||||
for lane in range(14)]
|
|
||||||
self.specials += Instance("ODDR",
|
# clock forwarding
|
||||||
i_C=ClockSignal("dco2d_45_degree"),
|
self.specials += DDROutput(
|
||||||
i_CE=~ResetSignal("dco2d"),
|
i1 = 0b0,
|
||||||
i_D1=0,
|
i2 = 0b1,
|
||||||
i_D2=1,
|
o = dac_pads.dclkio,
|
||||||
o_Q=dac_pads.dclkio,
|
clk = ClockSignal("dco2d"),
|
||||||
p_DDR_CLK_EDGE="SAME_EDGE")
|
)
|
||||||
|
|
||||||
|
|
||||||
class AUX_DAC_CTRL(Module, AutoCSR):
|
class AUX_DAC_CTRL(Module, AutoCSR):
|
||||||
|
@ -147,7 +147,6 @@ class BaseSoC(PS7, AutoCSR):
|
|||||||
# self.add_main_adc(platform)
|
# self.add_main_adc(platform)
|
||||||
self.submodules.adc = ADC(platform)
|
self.submodules.adc = ADC(platform)
|
||||||
self.csr_devices.append("adc")
|
self.csr_devices.append("adc")
|
||||||
platform.add_false_path_constraints(self.crg.cd_sys.clk, self.adc.crg.cd_dco2d.clk)
|
|
||||||
|
|
||||||
# self.add_main_dac(platform)
|
# self.add_main_dac(platform)
|
||||||
self.submodules.dac = DAC(platform)
|
self.submodules.dac = DAC(platform)
|
||||||
|
@ -1,227 +0,0 @@
|
|||||||
diff --git a/linien-gui/linien_gui/ui/general_panel.ui b/linien_gui/ui/general_panel.ui
|
|
||||||
index 7cf74a7..6c2bd45 100644
|
|
||||||
--- a/linien-gui/linien_gui/ui/general_panel.ui
|
|
||||||
+++ b/linien_gui/ui/general_panel.ui
|
|
||||||
@@ -128,11 +128,6 @@
|
|
||||||
<string>FAST OUT 2</string>
|
|
||||||
</property>
|
|
||||||
</item>
|
|
||||||
- <item>
|
|
||||||
- <property name="text">
|
|
||||||
- <string>ANALOG OUT 0</string>
|
|
||||||
- </property>
|
|
||||||
- </item>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
@@ -213,11 +208,6 @@
|
|
||||||
<string>FAST OUT 2</string>
|
|
||||||
</property>
|
|
||||||
</item>
|
|
||||||
- <item>
|
|
||||||
- <property name="text">
|
|
||||||
- <string>ANALOG OUT 0</string>
|
|
||||||
- </property>
|
|
||||||
- </item>
|
|
||||||
<item>
|
|
||||||
<property name="text">
|
|
||||||
<string>disabled</string>
|
|
||||||
@@ -389,6 +379,9 @@
|
|
||||||
<property name="text">
|
|
||||||
<string>ANALOG OUT 0</string>
|
|
||||||
</property>
|
|
||||||
+ <property name="visible">
|
|
||||||
+ <bool>false</bool>
|
|
||||||
+ </property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
@@ -399,6 +392,9 @@
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
+ <property name="visible">
|
|
||||||
+ <bool>false</bool>
|
|
||||||
+ </property>
|
|
||||||
<item>
|
|
||||||
<property name="text">
|
|
||||||
<string>positive</string>
|
|
||||||
@@ -619,6 +615,9 @@
|
|
||||||
<property name="title">
|
|
||||||
<string>Slow Analog Outputs (0-1.8V)</string>
|
|
||||||
</property>
|
|
||||||
+ <property name="visible">
|
|
||||||
+ <bool>false</bool>
|
|
||||||
+ </property>
|
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
|
||||||
<item>
|
|
||||||
<widget class="QLabel" name="label_20">
|
|
||||||
diff --git a/linien-gui/linien_gui/ui/main_window.ui b/linien_gui/ui/main_window.ui
|
|
||||||
index 3d8b8bf..72f6159 100644
|
|
||||||
--- a/linien-gui/linien_gui/ui/main_window.ui
|
|
||||||
+++ b/linien_gui/ui/main_window.ui
|
|
||||||
@@ -145,10 +145,10 @@ p, li { white-space: pre-wrap; }
|
|
||||||
<number>3</number>
|
|
||||||
</property>
|
|
||||||
<property name="minimum">
|
|
||||||
- <double>-1.000000000000000</double>
|
|
||||||
+ <double>-0.500000000000000</double>
|
|
||||||
</property>
|
|
||||||
<property name="maximum">
|
|
||||||
- <double>1.000000000000000</double>
|
|
||||||
+ <double>0.500000000000000</double>
|
|
||||||
</property>
|
|
||||||
<property name="singleStep">
|
|
||||||
<double>0.100000000000000</double>
|
|
||||||
@@ -199,13 +199,13 @@ p, li { white-space: pre-wrap; }lin
|
|
||||||
<double>0.000000000000000</double>
|
|
||||||
</property>
|
|
||||||
<property name="maximum">
|
|
||||||
- <double>1.000000000000000</double>
|
|
||||||
+ <double>0.500000000000000</double>
|
|
||||||
</property>
|
|
||||||
<property name="singleStep">
|
|
||||||
<double>0.100000000000000</double>
|
|
||||||
</property>
|
|
||||||
<property name="value">
|
|
||||||
- <double>1.000000000000000</double>
|
|
||||||
+ <double>0.500000000000000</double>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
@@ -242,7 +242,6 @@ p, li { white-space: pre-wrap; }
|
|
||||||
<widget class="QLabel" name="label_4">
|
|
||||||
<property name="font">
|
|
||||||
<font>
|
|
||||||
- <weight>75</weight>
|
|
||||||
<bold>true</bold>
|
|
||||||
</font>
|
|
||||||
</property>
|
|
||||||
@@ -278,7 +277,6 @@ p, li { white-space: pre-wrap; }
|
|
||||||
<widget class="QLabel" name="label_5">
|
|
||||||
<property name="font">
|
|
||||||
<font>
|
|
||||||
- <weight>75</weight>
|
|
||||||
<bold>true</bold>
|
|
||||||
</font>
|
|
||||||
</property>
|
|
||||||
@@ -366,7 +364,6 @@ p, li { white-space: pre-wrap; }
|
|
||||||
<widget class="QLabel" name="label">
|
|
||||||
<property name="font">
|
|
||||||
<font>
|
|
||||||
- <weight>75</weight>
|
|
||||||
<bold>true</bold>
|
|
||||||
</font>
|
|
||||||
</property>
|
|
||||||
diff --git a/linien-gui/linien_gui/ui/modulation_sweep_panel.ui b/linien_gui/ui/modulation_sweep_panel.ui
|
|
||||||
index 6d8af14..29c8a63 100644
|
|
||||||
--- a/linien-gui/linien_gui/ui/modulation_sweep_panel.ui
|
|
||||||
+++ b/linien_gui/ui/modulation_sweep_panel.ui
|
|
||||||
@@ -68,7 +68,7 @@
|
|
||||||
<number>3</number>
|
|
||||||
</property>
|
|
||||||
<property name="maximum">
|
|
||||||
- <double>2.000000000000000</double>
|
|
||||||
+ <double>0.500000000000000</double>
|
|
||||||
</property>
|
|
||||||
<property name="singleStep">
|
|
||||||
<double>0.100000000000000</double>
|
|
||||||
@@ -105,82 +105,82 @@
|
|
||||||
</property>
|
|
||||||
<item>
|
|
||||||
<property name="text">
|
|
||||||
- <string>3.8 kHz</string>
|
|
||||||
+ <string>3.04 kHz</string>
|
|
||||||
</property>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<property name="text">
|
|
||||||
- <string>1.9 kHz</string>
|
|
||||||
+ <string>1.52 kHz</string>
|
|
||||||
</property>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<property name="text">
|
|
||||||
- <string>954 Hz</string>
|
|
||||||
+ <string>763 Hz</string>
|
|
||||||
</property>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<property name="text">
|
|
||||||
- <string>477 Hz</string>
|
|
||||||
+ <string>382 Hz</string>
|
|
||||||
</property>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<property name="text">
|
|
||||||
- <string>238 Hz</string>
|
|
||||||
+ <string>190 Hz</string>
|
|
||||||
</property>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<property name="text">
|
|
||||||
- <string>119 Hz</string>
|
|
||||||
+ <string>95 Hz</string>
|
|
||||||
</property>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<property name="text">
|
|
||||||
- <string>59 Hz</string>
|
|
||||||
+ <string>47 Hz</string>
|
|
||||||
</property>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<property name="text">
|
|
||||||
- <string>30 Hz</string>
|
|
||||||
+ <string>24 Hz</string>
|
|
||||||
</property>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<property name="text">
|
|
||||||
- <string>15 Hz</string>
|
|
||||||
+ <string>12 Hz</string>
|
|
||||||
</property>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<property name="text">
|
|
||||||
- <string>7.5 Hz</string>
|
|
||||||
+ <string>6 Hz</string>
|
|
||||||
</property>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<property name="text">
|
|
||||||
- <string>3.7 Hz</string>
|
|
||||||
+ <string>2.96 Hz</string>
|
|
||||||
</property>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<property name="text">
|
|
||||||
- <string>1.9 Hz</string>
|
|
||||||
+ <string>1.52 Hz</string>
|
|
||||||
</property>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<property name="text">
|
|
||||||
- <string>0.93 Hz</string>
|
|
||||||
+ <string>0.74 Hz</string>
|
|
||||||
</property>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<property name="text">
|
|
||||||
- <string>0.47 Hz</string>
|
|
||||||
+ <string>0.38 Hz</string>
|
|
||||||
</property>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<property name="text">
|
|
||||||
- <string>0.23 Hz</string>
|
|
||||||
+ <string>0.18 Hz</string>
|
|
||||||
</property>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<property name="text">
|
|
||||||
- <string>0.12 Hz</string>
|
|
||||||
+ <string>0.10 Hz</string>
|
|
||||||
</property>
|
|
||||||
</item>
|
|
||||||
</widget>
|
|
@ -1,43 +0,0 @@
|
|||||||
diff --git a/linien_gui/ui/device_manager.py b/linien_gui/ui/device_manager.py
|
|
||||||
index e584825..16994ad 100644
|
|
||||||
--- a/linien_gui/ui/device_manager.py
|
|
||||||
+++ b/linien_gui/ui/device_manager.py
|
|
||||||
@@ -109,19 +109,13 @@ class DeviceManager(QtWidgets.QMainWindow):
|
|
||||||
) -> None:
|
|
||||||
loading_dialog.hide()
|
|
||||||
if not aborted:
|
|
||||||
- display_question = (
|
|
||||||
+ # Fast Servo does not support OTA Update
|
|
||||||
+ display_error = (
|
|
||||||
f"Server version ({remote_version}) does not match the client "
|
|
||||||
- f"({client_version}) version. Should the corresponding server "
|
|
||||||
- f"version be installed?"
|
|
||||||
+ f"({client_version}) version."
|
|
||||||
+ f"Please install a matching server and client version"
|
|
||||||
)
|
|
||||||
- if question_dialog(
|
|
||||||
- self, display_question, "Install corresponding version?"
|
|
||||||
- ):
|
|
||||||
- show_installation_progress_widget(
|
|
||||||
- parent=self,
|
|
||||||
- device=device,
|
|
||||||
- callback=lambda: self.connect_to_device(device),
|
|
||||||
- )
|
|
||||||
+ error_dialog(self, display_error)
|
|
||||||
|
|
||||||
def handle_authentication_exception():
|
|
||||||
loading_dialog.hide()
|
|
||||||
diff --git a/linien_gui/ui/main_window.py b/linien_gui/ui/main_window.py
|
|
||||||
index dad465e..8d6a0b4 100644
|
|
||||||
--- a/linien_gui/ui/main_window.py
|
|
||||||
+++ b/linien_gui/ui/main_window.py
|
|
||||||
@@ -202,7 +202,8 @@ class MainWindow(QtWidgets.QMainWindow):
|
|
||||||
super().closeEvent(*args, **kwargs)
|
|
||||||
|
|
||||||
def show_new_version_available(self):
|
|
||||||
- self.newVersionAvailableLabel.show()
|
|
||||||
+ # Fast Servo does not support OTA Update
|
|
||||||
+ pass
|
|
||||||
|
|
||||||
def handle_key_press(self, key):
|
|
||||||
logger.debug(f"key pressed {key}")
|
|
@ -1,95 +0,0 @@
|
|||||||
# 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..0c9bb53
|
|
||||||
--- /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 9302177..2258ddc 100644
|
|
||||||
--- a/setup.py
|
|
||||||
+++ b/setup.py
|
|
||||||
@@ -1,4 +1,28 @@
|
|
||||||
-from distutils.core import Extension, setup
|
|
||||||
+import os
|
|
||||||
+from distutils.core import setup
|
|
||||||
+from distutils.command.build import build
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+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)
|
|
||||||
+
|
|
||||||
+class lib_build(build):
|
|
||||||
+ def run(self):
|
|
||||||
+ compile_libmonitor()
|
|
||||||
+ build.run(self)
|
|
||||||
+
|
|
||||||
+setup_args = dict(
|
|
||||||
+ cmdclass={
|
|
||||||
+ "build": lib_build
|
|
||||||
+ }
|
|
||||||
+)
|
|
||||||
|
|
||||||
-setup_args = dict(ext_modules=[Extension("monitor", ["monitor/monitor.c"])])
|
|
||||||
setup(**setup_args)
|
|
@ -1,22 +0,0 @@
|
|||||||
diff --git a/linien-server/linien_server/parameters.py b/linien-server/linien_server/parameters.py
|
|
||||||
index 12f16ed..287f304 100644
|
|
||||||
--- a/linien-server/linien_server/parameters.py
|
|
||||||
+++ b/linien-server/linien_server/parameters.py
|
|
||||||
@@ -311,7 +311,7 @@ class Parameters:
|
|
||||||
# ------------------- MODULATION PARAMETERS ------------------------------------
|
|
||||||
|
|
||||||
self.modulation_amplitude = Parameter(
|
|
||||||
- min_=0, max_=(1 << 14) - 1, start=1 * Vpp, restorable=True, loggable=True
|
|
||||||
+ min_=0, max_=(1 << 14) - 1, start=0.1 * Vpp, restorable=True, loggable=True
|
|
||||||
)
|
|
||||||
"""
|
|
||||||
The amplitude of the modulation in internal units. Use Vpp for conversion to
|
|
||||||
@@ -320,7 +320,7 @@ class Parameters:
|
|
||||||
"""
|
|
||||||
|
|
||||||
self.modulation_frequency = Parameter(
|
|
||||||
- min_=0, max_=0xFFFFFFFF, start=15 * MHz, restorable=True, loggable=True
|
|
||||||
+ min_=0, max_=0xFFFFFFFF, start=1 * MHz, restorable=True, loggable=True
|
|
||||||
)
|
|
||||||
"""
|
|
||||||
Frequency of the modulation in internal units. Use MHz for conversion to
|
|
@ -1,26 +0,0 @@
|
|||||||
diff --git a/linien-server/linien_server/cli.py b/linien-server/linien_server/cli.py
|
|
||||||
index 98539b2..7781c74 100644
|
|
||||||
--- a/linien-server/linien_server/cli.py
|
|
||||||
+++ b/linien-server/linien_server/cli.py
|
|
||||||
@@ -83,18 +83,9 @@ class LinienServerCLI:
|
|
||||||
else:
|
|
||||||
control = RedPitayaControlService(host=host)
|
|
||||||
|
|
||||||
- if fake or host:
|
|
||||||
- authenticator = no_authenticator
|
|
||||||
- else:
|
|
||||||
- authenticator = username_and_password_authenticator
|
|
||||||
-
|
|
||||||
- try:
|
|
||||||
- if not (fake or host): # only available on RP
|
|
||||||
- mdio_tool.disable_ethernet_blinking()
|
|
||||||
- run_threaded_server(control, authenticator=authenticator)
|
|
||||||
- finally:
|
|
||||||
- if not (fake or host): # only available on RP
|
|
||||||
- mdio_tool.enable_ethernet_blinking()
|
|
||||||
+ authenticator = no_authenticator
|
|
||||||
+
|
|
||||||
+ run_threaded_server(control, authenticator=authenticator)
|
|
||||||
|
|
||||||
def enable(self) -> None:
|
|
||||||
"""Enable the Linien server to start on boot."""
|
|
@ -1,57 +0,0 @@
|
|||||||
diff --git a/gateware/linien_module.py b/gateware/linien_module.py
|
|
||||||
index a958896..a64714c 100644
|
|
||||||
--- a/gateware/linien_module.py
|
|
||||||
+++ b/gateware/linien_module.py
|
|
||||||
@@ -233,23 +233,46 @@ class LinienModule(Module, AutoCSR):
|
|
||||||
self.fast_a.adc.eq(soc.analog.adc_a),
|
|
||||||
self.fast_b.adc.eq(soc.analog.adc_b),
|
|
||||||
]
|
|
||||||
-
|
|
||||||
+
|
|
||||||
# now, we combine the output of the two paths, with a variable factor each.
|
|
||||||
mixed = Signal(
|
|
||||||
(2 + ((signal_width + 1) + self.logic.chain_a_factor.size), True)
|
|
||||||
)
|
|
||||||
+
|
|
||||||
+ chain_a_factor_mult_fast_a_out_i = Signal(
|
|
||||||
+ (2 + ((signal_width + 1) + self.logic.chain_a_factor.size), True)
|
|
||||||
+ )
|
|
||||||
+
|
|
||||||
+ chain_b_factor_mult_fast_b_out_i = Signal(
|
|
||||||
+ (2 + ((signal_width + 1) + self.logic.chain_a_factor.size), True)
|
|
||||||
+ )
|
|
||||||
+ combined_offset_signed_left_shifted = Signal(
|
|
||||||
+ (2 + ((signal_width + 1) + self.logic.chain_a_factor.size), True)
|
|
||||||
+ )
|
|
||||||
+ fast_a_out_i_left_shifted = Signal(
|
|
||||||
+ (2 + ((signal_width + 1) + self.logic.chain_a_factor.size), True)
|
|
||||||
+ )
|
|
||||||
+
|
|
||||||
+ self.sync += [
|
|
||||||
+ chain_a_factor_mult_fast_a_out_i.eq(self.logic.chain_a_factor.storage * self.fast_a.out_i),
|
|
||||||
+ chain_b_factor_mult_fast_b_out_i.eq(self.logic.chain_b_factor.storage * self.fast_b.out_i),
|
|
||||||
+ combined_offset_signed_left_shifted.eq(self.logic.combined_offset_signed << (chain_factor_bits + s)),
|
|
||||||
+ fast_a_out_i_left_shifted.eq(self.fast_a.out_i << chain_factor_bits),
|
|
||||||
+ ]
|
|
||||||
+
|
|
||||||
+
|
|
||||||
self.comb += [
|
|
||||||
If(
|
|
||||||
self.logic.dual_channel.storage,
|
|
||||||
mixed.eq(
|
|
||||||
- (self.logic.chain_a_factor.storage * self.fast_a.out_i)
|
|
||||||
- + (self.logic.chain_b_factor.storage * self.fast_b.out_i)
|
|
||||||
- + (self.logic.combined_offset_signed << (chain_factor_bits + s))
|
|
||||||
+ chain_a_factor_mult_fast_a_out_i
|
|
||||||
+ + chain_b_factor_mult_fast_b_out_i
|
|
||||||
+ + combined_offset_signed_left_shifted
|
|
||||||
),
|
|
||||||
).Else(
|
|
||||||
mixed.eq(
|
|
||||||
- (self.fast_a.out_i << chain_factor_bits)
|
|
||||||
- + (self.logic.combined_offset_signed << (chain_factor_bits + s))
|
|
||||||
+ fast_a_out_i_left_shifted
|
|
||||||
+ + combined_offset_signed_left_shifted
|
|
||||||
)
|
|
||||||
)
|
|
||||||
]
|
|
@ -1,19 +0,0 @@
|
|||||||
diff --git a/gateware/logic/pid.py b/gateware/logic/pid.py
|
|
||||||
index e737577..f1a4096 100644
|
|
||||||
--- a/gateware/logic/pid.py
|
|
||||||
+++ b/gateware/logic/pid.py
|
|
||||||
@@ -43,10 +43,12 @@ class PID(Module, AutoCSR):
|
|
||||||
self.comb += [setpoint_signed.eq(self.setpoint.storage)]
|
|
||||||
|
|
||||||
self.error = Signal((self.width + 1, True))
|
|
||||||
+ error_reg = Signal((self.width + 1, True))
|
|
||||||
+ self.sync += self.error.eq(error_reg)
|
|
||||||
|
|
||||||
self.comb += [
|
|
||||||
- If(self.running, self.error.eq(self.input - self.setpoint.storage)).Else(
|
|
||||||
- self.error.eq(0)
|
|
||||||
+ If(self.running, error_reg.eq(self.input - self.setpoint.storage)).Else(
|
|
||||||
+ error_reg.eq(0)
|
|
||||||
)
|
|
||||||
]
|
|
||||||
|
|
@ -1,64 +0,0 @@
|
|||||||
diff --git a/gateware/logic/pid.py b/gateware/logic/pid.py
|
|
||||||
index 4320f94..e737577 100644
|
|
||||||
--- a/gateware/logic/pid.py
|
|
||||||
+++ b/gateware/logic/pid.py
|
|
||||||
@@ -56,10 +56,13 @@ class PID(Module, AutoCSR):
|
|
||||||
self.comb += [kp_signed.eq(self.kp.storage)]
|
|
||||||
|
|
||||||
kp_mult = Signal((self.width + self.coeff_width, True))
|
|
||||||
- self.comb += [kp_mult.eq(self.error * kp_signed)]
|
|
||||||
+ kp_mult_reg = Signal((self.width + self.coeff_width, True))
|
|
||||||
+ self.sync += kp_mult.eq(kp_mult_reg >> (self.coeff_width - 2))
|
|
||||||
+
|
|
||||||
+ self.comb += [kp_mult_reg.eq(self.error * kp_signed)]
|
|
||||||
|
|
||||||
self.output_p = Signal((self.width, True))
|
|
||||||
- self.comb += [self.output_p.eq(kp_mult >> (self.coeff_width - 2))]
|
|
||||||
+ self.comb += [self.output_p.eq(kp_mult)]
|
|
||||||
|
|
||||||
self.kp_mult = kp_mult
|
|
||||||
|
|
||||||
@@ -71,8 +74,10 @@ class PID(Module, AutoCSR):
|
|
||||||
self.comb += [ki_signed.eq(self.ki.storage)]
|
|
||||||
|
|
||||||
self.ki_mult = Signal((1 + self.width + self.coeff_width, True))
|
|
||||||
+ self.ki_mult_reg = Signal((1 + self.width + self.coeff_width, True))
|
|
||||||
+ self.sync += self.ki_mult.eq(self.ki_mult_reg)
|
|
||||||
+ self.comb += self.ki_mult_reg.eq((self.error * ki_signed) >> 4)
|
|
||||||
|
|
||||||
- self.comb += [self.ki_mult.eq((self.error * ki_signed) >> 4)]
|
|
||||||
|
|
||||||
int_reg_width = self.width + self.coeff_width + 4
|
|
||||||
extra_width = int_reg_width - self.width
|
|
||||||
@@ -110,15 +115,17 @@ class PID(Module, AutoCSR):
|
|
||||||
self.kd = CSRStorage(self.coeff_width)
|
|
||||||
kd_signed = Signal((self.coeff_width, True))
|
|
||||||
kd_mult = Signal((mult_width, True))
|
|
||||||
+ kd_mult_reg = Signal((mult_width, True))
|
|
||||||
+ self.sync += kd_mult.eq(kd_mult_reg)
|
|
||||||
|
|
||||||
- self.comb += [kd_signed.eq(self.kd.storage), kd_mult.eq(self.error * kd_signed)]
|
|
||||||
+ self.comb += [kd_signed.eq(self.kd.storage), kd_mult_reg.eq(self.error * kd_signed >> (self.coeff_width - self.d_shift))]
|
|
||||||
|
|
||||||
kd_reg = Signal((out_width, True))
|
|
||||||
kd_reg_r = Signal((out_width, True))
|
|
||||||
|
|
||||||
self.output_d = Signal((out_width, True))
|
|
||||||
self.sync += [
|
|
||||||
- kd_reg.eq(kd_mult >> (self.coeff_width - self.d_shift)),
|
|
||||||
+ kd_reg.eq(kd_mult),
|
|
||||||
kd_reg_r.eq(kd_reg),
|
|
||||||
self.output_d.eq(kd_reg - kd_reg_r),
|
|
||||||
]
|
|
||||||
@@ -143,4 +150,10 @@ class PID(Module, AutoCSR):
|
|
||||||
|
|
||||||
# sync is required here, otherwise we get artifacts when one of the
|
|
||||||
# signals changes sign
|
|
||||||
- self.sync += [self.pid_sum.eq(self.output_p + self.int_out + self.output_d)]
|
|
||||||
+ self.sync += [
|
|
||||||
+ If(
|
|
||||||
+ self.running,
|
|
||||||
+ self.pid_sum.eq(self.output_p + self.int_out + self.output_d),
|
|
||||||
+ )
|
|
||||||
+ .Else(self.pid_sum.eq(0))
|
|
||||||
+ ]
|
|
@ -17,9 +17,11 @@
|
|||||||
# 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 time
|
import mmap
|
||||||
|
import os
|
||||||
|
|
||||||
import spidev
|
import spidev
|
||||||
from pyfastservo.common import (
|
from common import (
|
||||||
ADC_AFE_CTRL_ADDR,
|
ADC_AFE_CTRL_ADDR,
|
||||||
ADC_BITSLIP_ADDR,
|
ADC_BITSLIP_ADDR,
|
||||||
ADC_CH0_HIGH_ADDR,
|
ADC_CH0_HIGH_ADDR,
|
||||||
@ -31,8 +33,6 @@ from pyfastservo.common import (
|
|||||||
AUX_ADC_ADDR,
|
AUX_ADC_ADDR,
|
||||||
MAP_MASK,
|
MAP_MASK,
|
||||||
PAGESIZE,
|
PAGESIZE,
|
||||||
write_to_memory,
|
|
||||||
read_from_memory
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# /dev/spidev1.0 <=> spidev<BUS>.<DEVICE>
|
# /dev/spidev1.0 <=> spidev<BUS>.<DEVICE>
|
||||||
@ -44,181 +44,276 @@ AUX_ADC_PORT_A = 2
|
|||||||
AUX_ADC_PORT_B = 3
|
AUX_ADC_PORT_B = 3
|
||||||
|
|
||||||
|
|
||||||
def spi_write(spi, address, value):
|
def main_adc_config(test_pattern):
|
||||||
spi.xfer2([address, value])
|
|
||||||
|
|
||||||
def spi_read(spi, address):
|
|
||||||
rx_buffer = spi.xfer2([0x80 | address, 0x00])
|
|
||||||
return rx_buffer[1]
|
|
||||||
|
|
||||||
def main_adc_config(spi, test_pattern):
|
|
||||||
high_word = (test_pattern & 0xFF00) >> 8
|
high_word = (test_pattern & 0xFF00) >> 8
|
||||||
low_word = test_pattern & 0xFF
|
low_word = test_pattern & 0xFF
|
||||||
|
|
||||||
spi_write(spi, 0x00, 0x80) # reset
|
|
||||||
spi_write(spi, 0x01, 0x20) # REGISTER A1: set to Two's complement Data Format
|
|
||||||
spi_write(spi, 0x02, 0x15) # REGISTER A2: set to LVDS output, set 4 data lanes and turn on test mode
|
|
||||||
spi_write(spi, 0x03, high_word) # REGISTER A3: test pattern high word
|
|
||||||
spi_write(spi, 0x04, low_word) # REGISTER A4: test pattern low word
|
|
||||||
|
|
||||||
def main_adc_test_mode(spi, enable):
|
|
||||||
reg_contents = 0x15 if enable else 0x11 # set to LVDS output, set 4 data lanes and turn on or off test mode
|
|
||||||
spi_write(spi, 0x02, reg_contents)
|
|
||||||
|
|
||||||
def verify_adc_registers(spi, reg_to_check):
|
|
||||||
for register, expected_value in reg_to_check.items():
|
|
||||||
value = spi_read(spi, register)
|
|
||||||
print(f"Spi readback register 0x{register:02x}: 0x{value:02x}")
|
|
||||||
if value != expected_value:
|
|
||||||
print(f"Different value read than sent in reg 0x{register:02x}")
|
|
||||||
|
|
||||||
def read_frame():
|
|
||||||
return read_from_memory(ADC_FRAME_ADDR, 1)[0]
|
|
||||||
|
|
||||||
def perform_bitslip():
|
|
||||||
for i in range(4):
|
|
||||||
current_frame = read_frame()
|
|
||||||
if current_frame & 0x0F != 0x0C:
|
|
||||||
print(f"Performing bitslip (iteration: {i}). Current frame: 0x{current_frame:02x}")
|
|
||||||
write_to_memory(ADC_BITSLIP_ADDR, 1)
|
|
||||||
else:
|
|
||||||
print(f"No bitslip required; Current frame: 0x{current_frame:02x}")
|
|
||||||
return
|
|
||||||
|
|
||||||
def mmcm_rst():
|
|
||||||
curr_cfg = read_from_memory(ADC_AFE_CTRL_ADDR, 1)[0] & 0x0F
|
|
||||||
write_to_memory(ADC_AFE_CTRL_ADDR, 0x10 | curr_cfg) # Reset MMCM
|
|
||||||
write_to_memory(ADC_AFE_CTRL_ADDR, 0x00 | curr_cfg) # Release MMCM Reset
|
|
||||||
while not(read_frame() & 0x10):
|
|
||||||
print(f"Waiting for MMCM to lock")
|
|
||||||
time.sleep(0.001)
|
|
||||||
|
|
||||||
def inc_ddr_clk_phase():
|
|
||||||
curr_cfg = read_from_memory(ADC_AFE_CTRL_ADDR, 1)[0] & 0x1F
|
|
||||||
write_to_memory(ADC_AFE_CTRL_ADDR, 0x40 | curr_cfg) # Set MMCM Phase Shift to be INC
|
|
||||||
write_to_memory(ADC_AFE_CTRL_ADDR, 0x60 | curr_cfg) # Assert MMCM Phase Shift EN High
|
|
||||||
write_to_memory(ADC_AFE_CTRL_ADDR, curr_cfg) # Deassert MMCM Phase Shift EN High
|
|
||||||
|
|
||||||
def dec_ddr_clk_phase():
|
|
||||||
curr_cfg = read_from_memory(ADC_AFE_CTRL_ADDR, 1)[0] & 0x1F
|
|
||||||
write_to_memory(ADC_AFE_CTRL_ADDR, 0x00 | curr_cfg) # Set MMCM Phase Shift to be DEC
|
|
||||||
write_to_memory(ADC_AFE_CTRL_ADDR, 0x20 | curr_cfg) # Assert MMCM Phase Shift EN High
|
|
||||||
write_to_memory(ADC_AFE_CTRL_ADDR, curr_cfg) # Deassert MMCM Phase Shift EN High
|
|
||||||
|
|
||||||
def find_edge():
|
|
||||||
prev_frame = read_frame()
|
|
||||||
for tap_delay in range(32):
|
|
||||||
write_to_memory(ADC_DELAY_ADDR, tap_delay)
|
|
||||||
current_frame = read_frame()
|
|
||||||
|
|
||||||
print(f"Tap delay: {tap_delay}, Current frame: 0x{current_frame:02x}")
|
|
||||||
print(f"prev_frame: 0x{prev_frame:02x}")
|
|
||||||
|
|
||||||
if current_frame != prev_frame:
|
|
||||||
final_delay = ((tap_delay+1) // 2) + 2
|
|
||||||
print(f"Edge detected; setting iDelay to: {final_delay}")
|
|
||||||
write_to_memory(ADC_DELAY_ADDR, final_delay)
|
|
||||||
return
|
|
||||||
|
|
||||||
prev_frame = current_frame
|
|
||||||
|
|
||||||
# If no edge detected
|
|
||||||
final_delay = 11
|
|
||||||
print(f"No edge detected; setting iDelay to: {final_delay}")
|
|
||||||
write_to_memory(ADC_DELAY_ADDR, final_delay)
|
|
||||||
|
|
||||||
def read_adc_channel(high_addr, low_addr):
|
|
||||||
return (read_from_memory(high_addr, 1)[0] << 8) | read_from_memory(low_addr, 1)[0]
|
|
||||||
|
|
||||||
def print_adc_channels():
|
|
||||||
adc_ch0 = read_adc_channel(ADC_CH0_HIGH_ADDR, ADC_CH0_LOW_ADDR)
|
|
||||||
adc_ch1 = read_adc_channel(ADC_CH1_HIGH_ADDR, ADC_CH1_LOW_ADDR)
|
|
||||||
print(f"Final ADC_CH0: 0x{adc_ch0:04x}")
|
|
||||||
print(f"Final ADC_CH1: 0x{adc_ch1:04x}")
|
|
||||||
|
|
||||||
def enable_adc_afe(ch1_x10=False, ch2_x10=False):
|
|
||||||
ctrl_value = (ch2_x10 << 1) | ch1_x10
|
|
||||||
write_to_memory(ADC_AFE_CTRL_ADDR, ctrl_value)
|
|
||||||
afe_ctrl = read_from_memory(ADC_AFE_CTRL_ADDR, 1)[0]
|
|
||||||
print(f"ADC_AFE_CTRL: 0x{afe_ctrl:02X}")
|
|
||||||
return afe_ctrl
|
|
||||||
|
|
||||||
def search_edge():
|
|
||||||
for tap_delay in range(32):
|
|
||||||
print(f"iDelay to: {tap_delay}")
|
|
||||||
write_to_memory(ADC_DELAY_ADDR, tap_delay)
|
|
||||||
time.sleep(1)
|
|
||||||
current_frame = read_frame()
|
|
||||||
print(f"Tap delay: {tap_delay}, Current frame: 0x{current_frame:02x}")
|
|
||||||
print_adc_channels()
|
|
||||||
|
|
||||||
def print_adc_channel(ch):
|
|
||||||
if ch == 0:
|
|
||||||
adc_ch0 = read_adc_channel(ADC_CH0_HIGH_ADDR, ADC_CH0_LOW_ADDR)
|
|
||||||
print(f"Final ADC_CH0: 0x{adc_ch0:04x}")
|
|
||||||
if ch == 1:
|
|
||||||
adc_ch1 = read_adc_channel(ADC_CH1_HIGH_ADDR, ADC_CH1_LOW_ADDR)
|
|
||||||
print(f"Final ADC_CH1: 0x{adc_ch1:04x}")
|
|
||||||
|
|
||||||
def find_min_max_ch(ch):
|
|
||||||
test = []
|
|
||||||
for i in range(100):
|
|
||||||
if ch == 0:
|
|
||||||
test.append(read_adc_channel(ADC_CH0_HIGH_ADDR, ADC_CH0_LOW_ADDR))
|
|
||||||
else:
|
|
||||||
test.append(read_adc_channel(ADC_CH1_HIGH_ADDR, ADC_CH1_LOW_ADDR))
|
|
||||||
print("ch", ch, hex(test[-1]))
|
|
||||||
print("Min:", hex(min(test)))
|
|
||||||
print("Max:", hex(max(test)))
|
|
||||||
print("Diff:", hex(max(test)-min(test)))
|
|
||||||
|
|
||||||
|
|
||||||
def configure_ltc2195():
|
|
||||||
spi = spidev.SpiDev()
|
spi = spidev.SpiDev()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
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 = False
|
spi.cshigh = True
|
||||||
|
# spi.read0 = False
|
||||||
|
|
||||||
test_pattern = 0x811F
|
spi_buffer = [0x00, 0x80] # reset
|
||||||
main_adc_config(spi, test_pattern)
|
rx_buffer = [0x00, 0x00]
|
||||||
|
|
||||||
verify_adc_registers(spi, {
|
spi.xfer2(spi_buffer)
|
||||||
0x01: 0x20,
|
|
||||||
0x02: 0x15,
|
|
||||||
0x03: (test_pattern & 0xFF00) >> 8,
|
|
||||||
0x04: test_pattern & 0xFF
|
|
||||||
})
|
|
||||||
|
|
||||||
# ADC software reset put its PLL to sleep momentarily. Thus, MMCM needs to be reset as well.
|
# REGISTER A1
|
||||||
mmcm_rst()
|
spi_buffer = [0x01, 0x20] # set to Two's complement Data Format
|
||||||
|
spi.xfer2(spi_buffer)
|
||||||
# Performing Word Align
|
|
||||||
perform_bitslip()
|
|
||||||
find_edge()
|
|
||||||
|
|
||||||
# Printing it once is not enough to check whether the alignment is correct.
|
|
||||||
for i in range(100):
|
|
||||||
print_adc_channels()
|
|
||||||
|
|
||||||
main_adc_test_mode(spi, False)
|
# read values back
|
||||||
verify_adc_registers(spi, {0x02: 0x11}) # Verify test mode is off
|
spi_buffer = [0x81, 0x00]
|
||||||
|
rx_buffer = spi.xfer2(spi_buffer)
|
||||||
# FIXME: AFE Gain 1x is not functional on that batch of fast servo under development
|
print(f"Spi readback register 0x01: 0x{rx_buffer[1]:02x}")
|
||||||
enable_adc_afe(ch1_x10=1, ch2_x10=1)
|
if rx_buffer[1] != 0x20:
|
||||||
|
print("Different value read than sent in reg 0x02")
|
||||||
|
|
||||||
#find_min_max_ch(0)
|
# REGISTER A2
|
||||||
#find_min_max_ch(1)
|
spi_buffer = [
|
||||||
|
0x02,
|
||||||
|
0x15,
|
||||||
|
] # set to LVDS output, set 4 data lanes and turn on test mode
|
||||||
|
spi.xfer2(spi_buffer)
|
||||||
|
|
||||||
#for i in range(10):
|
# read values back
|
||||||
# print_adc_channel(0)
|
spi_buffer = [0x82, 0x00]
|
||||||
|
rx_buffer = spi.xfer2(spi_buffer)
|
||||||
|
print(f"Spi readback register 0x02: 0x{rx_buffer[1]:02x}")
|
||||||
|
if rx_buffer[1] != 0x15:
|
||||||
|
print("Different value read than sent in reg 0x02")
|
||||||
|
|
||||||
#for i in range(10):
|
# REGISTER A3
|
||||||
# print_adc_channel(1)
|
# test pattern high word
|
||||||
|
spi_buffer = [0x03, high_word]
|
||||||
|
spi.xfer2(spi_buffer)
|
||||||
|
|
||||||
|
# read balues back
|
||||||
|
spi_buffer = [0x83, 0x00]
|
||||||
|
rx_buffer = spi.xfer2(spi_buffer)
|
||||||
|
print(f"Spi readback register 0x03: 0x{rx_buffer[1]:02x}")
|
||||||
|
if rx_buffer[1] != high_word:
|
||||||
|
print("Different value read than sent in reg 0x03")
|
||||||
|
|
||||||
|
# REGISTER A4
|
||||||
|
# test pattern low word
|
||||||
|
spi_buffer = [0x04, low_word]
|
||||||
|
spi.xfer2(spi_buffer)
|
||||||
|
|
||||||
|
# read balues back
|
||||||
|
spi_buffer = [0x84, 0x00]
|
||||||
|
rx_buffer = spi.xfer2(spi_buffer)
|
||||||
|
print(f"Spi readback register 0x04: 0x{rx_buffer[1]:02x}")
|
||||||
|
if rx_buffer[1] != low_word:
|
||||||
|
print("Different value read than sent in reg 0x04")
|
||||||
|
finally:
|
||||||
|
spi.close()
|
||||||
|
|
||||||
|
|
||||||
|
def main_adc_test_mode(enable):
|
||||||
|
spi = spidev.SpiDev()
|
||||||
|
|
||||||
|
try:
|
||||||
|
spi.open(MAIN_ADC_BUS, MAIN_ADC_DEVICE)
|
||||||
|
spi.max_speed_hz = 50000
|
||||||
|
spi.mode = 0b00 # CPOL = 0 CPHA = 0
|
||||||
|
spi.cshigh = True
|
||||||
|
# spi.read0 = True
|
||||||
|
|
||||||
|
reg_contents = (
|
||||||
|
0x15 if enable else 0x11
|
||||||
|
) # set to LVDS output, set 4 data lanes and turn on or off test mode
|
||||||
|
spi_buffer = [0x02, reg_contents]
|
||||||
|
spi.xfer2(spi_buffer)
|
||||||
|
|
||||||
|
# read values back
|
||||||
|
spi_buffer = [0x82, 0x00]
|
||||||
|
rx_buffer = spi.xfer2(spi_buffer)
|
||||||
|
print(f"Spi readback register 0x02: 0x{rx_buffer[1]:02x}")
|
||||||
|
if rx_buffer[1] != reg_contents:
|
||||||
|
print("Different value read than sent in reg 0x02")
|
||||||
|
finally:
|
||||||
|
spi.close()
|
||||||
|
|
||||||
|
|
||||||
|
def read_from_memory(address, n_bytes):
|
||||||
|
assert n_bytes <= 4
|
||||||
|
addr = address
|
||||||
|
|
||||||
|
try:
|
||||||
|
f = os.open("/dev/mem", os.O_SYNC | os.O_RDWR)
|
||||||
|
with mmap.mmap(
|
||||||
|
f,
|
||||||
|
PAGESIZE,
|
||||||
|
mmap.MAP_SHARED,
|
||||||
|
mmap.PROT_READ | mmap.PROT_WRITE,
|
||||||
|
offset=addr & ~MAP_MASK,
|
||||||
|
) as mem:
|
||||||
|
start_addr = addr & MAP_MASK
|
||||||
|
stop_addr = start_addr + 4
|
||||||
|
# print(f"addr: 0x{addr:x}\tstart_addr: 0x{start_addr}\tstop_addr: 0x{stop_addr}")
|
||||||
|
contents = mem[start_addr:stop_addr]
|
||||||
|
read_value = list(contents)[:n_bytes]
|
||||||
|
# print("Read value: ", read_value)
|
||||||
|
finally:
|
||||||
|
os.close(f)
|
||||||
|
|
||||||
|
return read_value
|
||||||
|
|
||||||
|
|
||||||
|
def write_to_memory(address, value):
|
||||||
|
value_bytes = value.to_bytes(4, "little")
|
||||||
|
addr = address
|
||||||
|
|
||||||
|
try:
|
||||||
|
f = os.open("/dev/mem", os.O_SYNC | os.O_RDWR)
|
||||||
|
with mmap.mmap(
|
||||||
|
f,
|
||||||
|
PAGESIZE,
|
||||||
|
mmap.MAP_SHARED,
|
||||||
|
mmap.PROT_READ | mmap.PROT_WRITE,
|
||||||
|
offset=addr & ~MAP_MASK,
|
||||||
|
) as mem:
|
||||||
|
start_addr = addr & MAP_MASK
|
||||||
|
stop_addr = start_addr + 4
|
||||||
|
# print(f"addr: 0x{addr:x}\tstart_addr: 0x{start_addr}\tstop_addr: 0x{stop_addr}")
|
||||||
|
mem[start_addr:stop_addr] = value_bytes
|
||||||
|
contents = mem[start_addr:stop_addr]
|
||||||
|
# print("Read value: ", list(contents), " written value: ", list(value_bytes))
|
||||||
|
finally:
|
||||||
|
os.close(f)
|
||||||
|
|
||||||
|
|
||||||
|
def word_align():
|
||||||
|
|
||||||
|
value = 0
|
||||||
|
edge_detected = False
|
||||||
|
transition = False
|
||||||
|
tap_delay = 0
|
||||||
|
|
||||||
|
for i in range(4):
|
||||||
|
current_frame = read_from_memory(ADC_FRAME_ADDR, 1)[0]
|
||||||
|
if current_frame != 0x0C:
|
||||||
|
print(
|
||||||
|
f"Performing bitslip (bitslip iteration: {i}). Reason: current_frame is 0x{current_frame:02x} instead of 0x0C"
|
||||||
|
)
|
||||||
|
write_to_memory(ADC_BITSLIP_ADDR, 1)
|
||||||
|
else:
|
||||||
|
print(f"No bitslip required; Currernt frame = 0x{current_frame:02x}")
|
||||||
|
break
|
||||||
|
|
||||||
|
current_frame = read_from_memory(ADC_FRAME_ADDR, 1)[0]
|
||||||
|
prev_frame = current_frame
|
||||||
|
|
||||||
|
for i in range(32):
|
||||||
|
write_to_memory(ADC_DELAY_ADDR, tap_delay)
|
||||||
|
if edge_detected == 1:
|
||||||
|
break
|
||||||
|
current_frame = read_from_memory(ADC_FRAME_ADDR, 1)[0]
|
||||||
|
|
||||||
|
print(f"Tap delay: {tap_delay}")
|
||||||
|
print(f"Current frame: 0x{current_frame:02x}")
|
||||||
|
|
||||||
|
if current_frame == prev_frame:
|
||||||
|
tap_delay += 1
|
||||||
|
elif not transition:
|
||||||
|
tap_delay += 1
|
||||||
|
transition = True
|
||||||
|
elif transition:
|
||||||
|
tap_delay = i // 2
|
||||||
|
edge_detected = True
|
||||||
|
|
||||||
|
prev_frame = current_frame
|
||||||
|
|
||||||
|
if not edge_detected:
|
||||||
|
tap_delay = 11 # empirically tested to work best
|
||||||
|
write_to_memory(ADC_DELAY_ADDR, tap_delay)
|
||||||
|
print(f"No edge detected; setting iDelay to: {tap_delay}")
|
||||||
|
if edge_detected:
|
||||||
|
write_to_memory(ADC_DELAY_ADDR, tap_delay + 2)
|
||||||
|
print(f"Edge detected; setting iDelay to (tap_delay + 2): {tap_delay} + 2")
|
||||||
|
|
||||||
|
adc_ch0 = read_from_memory(ADC_CH0_HIGH_ADDR, 4)
|
||||||
|
print(f"ADC_CH0: 0x{adc_ch0}")
|
||||||
|
|
||||||
|
adc_ch0 = (read_from_memory(ADC_CH0_HIGH_ADDR, 1)[0] << 8) | read_from_memory(
|
||||||
|
ADC_CH0_LOW_ADDR, 1
|
||||||
|
)[0]
|
||||||
|
adc_ch1 = (read_from_memory(ADC_CH1_HIGH_ADDR, 1)[0] << 8) | read_from_memory(
|
||||||
|
ADC_CH1_LOW_ADDR, 1
|
||||||
|
)[0]
|
||||||
|
print(f"Final ADC_CH0: 0x{adc_ch0:04x}")
|
||||||
|
print(f"Final ADC_CH1: 0x{adc_ch1:04x}")
|
||||||
|
|
||||||
|
|
||||||
|
def modify_bit(original_value, position, bit_value):
|
||||||
|
mask = 1 << position
|
||||||
|
return (original_value & ~mask) | (bit_value << position)
|
||||||
|
|
||||||
|
|
||||||
|
def adc_aux_config():
|
||||||
|
# MSB to LSB
|
||||||
|
# | RANGE | ADDR [2:0] | DIFF |
|
||||||
|
# DIFF = 0 => configure as single ended (it is negated in gateware)
|
||||||
|
# RANGE = 0 => configure as 0-2.5 Vref
|
||||||
|
to_write = 0b00000
|
||||||
|
write_to_memory(AUX_ADC_ADDR, to_write)
|
||||||
|
|
||||||
|
|
||||||
|
def adc_aux_read(port, type, pin):
|
||||||
|
# port:
|
||||||
|
# 1 - port A
|
||||||
|
# 2 - port B
|
||||||
|
# type:
|
||||||
|
# 0 - single-ended
|
||||||
|
# 1 - differential
|
||||||
|
# pin:
|
||||||
|
# 0b000 - VA1/VB1
|
||||||
|
# 0b001 - VA2/VB2
|
||||||
|
# 0b010 - VA3/VB3
|
||||||
|
# 0b011 - VA4/VB4
|
||||||
|
|
||||||
|
assert type in (0, 1)
|
||||||
|
assert port in (1, 2)
|
||||||
|
|
||||||
|
write_buffer = [0, 0]
|
||||||
|
read_buffer = [0, 0]
|
||||||
|
|
||||||
|
aux_config_reg = read_from_memory(AUX_ADC_ADDR, 1)[0]
|
||||||
|
aux_config = (aux_config_reg & 0b10001) | pin << 1
|
||||||
|
write_to_memory(AUX_ADC_ADDR, aux_config)
|
||||||
|
|
||||||
|
spi = spidev.SpiDev()
|
||||||
|
try:
|
||||||
|
spi.open(1, 3) # AUX ADC 1?
|
||||||
|
spi.max_speed_hz = 5000
|
||||||
|
spi.mode = 0b00
|
||||||
|
spi.cshigh = True
|
||||||
|
|
||||||
|
read_buffer = spi.xfer2(write_buffer)
|
||||||
|
mu_voltage = read_buffer[0] << 8 | read_buffer[1] >> 2
|
||||||
|
print(f"MU_voltage: 0x{mu_voltage:04X}")
|
||||||
|
print(f"Read_buffer[0]: 0x{read_buffer[0]:02X}")
|
||||||
|
print(f"Read_buffer[1]: 0x{read_buffer[1]:02X}")
|
||||||
|
return mu_voltage * 2.5 / 4096
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
spi.close()
|
spi.close()
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
main_adc_config(0x811F)
|
||||||
|
word_align()
|
||||||
|
|
||||||
|
main_adc_test_mode(False)
|
||||||
|
|
||||||
|
write_to_memory(ADC_AFE_CTRL_ADDR, 0b1100) # {-, -, ch2_X10, ch1_X10}
|
||||||
|
print(read_from_memory(ADC_AFE_CTRL_ADDR, 1)[0])
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
configure_ltc2195()
|
main()
|
@ -17,16 +17,13 @@
|
|||||||
# 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 os
|
|
||||||
import mmap
|
|
||||||
|
|
||||||
CSR_SIZE = 0x800
|
CSR_SIZE = 0x800
|
||||||
MAP_SIZE = 0x1000
|
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
|
||||||
@ -74,47 +71,4 @@ CTRL_ADDR = DAC_BASE_ADDR + CTRL_OFFSET
|
|||||||
CH0_HIGH_WORD_ADDR = DAC_BASE_ADDR + CH0_HIGH_WORD_OFFSET
|
CH0_HIGH_WORD_ADDR = DAC_BASE_ADDR + CH0_HIGH_WORD_OFFSET
|
||||||
CH0_LOW_WORD_ADDR = DAC_BASE_ADDR + CH0_LOW_WORD_OFFSET
|
CH0_LOW_WORD_ADDR = DAC_BASE_ADDR + CH0_LOW_WORD_OFFSET
|
||||||
CH1_HIGH_WORD_ADDR = DAC_BASE_ADDR + CH1_HIGH_WORD_OFFSET
|
CH1_HIGH_WORD_ADDR = DAC_BASE_ADDR + CH1_HIGH_WORD_OFFSET
|
||||||
CH1_LOW_WORD_ADDR = DAC_BASE_ADDR + CH1_LOW_WORD_OFFSET
|
CH1_LOW_WORD_ADDR = DAC_BASE_ADDR + CH1_LOW_WORD_OFFSET
|
||||||
|
|
||||||
|
|
||||||
def read_from_memory(address, n_bytes):
|
|
||||||
assert n_bytes <= 4
|
|
||||||
addr = address
|
|
||||||
|
|
||||||
try:
|
|
||||||
f = os.open("/dev/mem", os.O_SYNC | os.O_RDWR)
|
|
||||||
with mmap.mmap(
|
|
||||||
f,
|
|
||||||
PAGESIZE,
|
|
||||||
mmap.MAP_SHARED,
|
|
||||||
mmap.PROT_READ | mmap.PROT_WRITE,
|
|
||||||
offset=addr & ~MAP_MASK,
|
|
||||||
) as mem:
|
|
||||||
start_addr = addr & MAP_MASK
|
|
||||||
stop_addr = start_addr + 4
|
|
||||||
contents = mem[start_addr:stop_addr]
|
|
||||||
read_value = list(contents)[:n_bytes]
|
|
||||||
finally:
|
|
||||||
os.close(f)
|
|
||||||
|
|
||||||
return read_value
|
|
||||||
|
|
||||||
def write_to_memory(address, value):
|
|
||||||
value_bytes = value.to_bytes(4, "little")
|
|
||||||
addr = address
|
|
||||||
|
|
||||||
try:
|
|
||||||
f = os.open("/dev/mem", os.O_SYNC | os.O_RDWR)
|
|
||||||
with mmap.mmap(
|
|
||||||
f,
|
|
||||||
PAGESIZE,
|
|
||||||
mmap.MAP_SHARED,
|
|
||||||
mmap.PROT_READ | mmap.PROT_WRITE,
|
|
||||||
offset=addr & ~MAP_MASK,
|
|
||||||
) as mem:
|
|
||||||
start_addr = addr & MAP_MASK
|
|
||||||
stop_addr = start_addr + 4
|
|
||||||
mem[start_addr:stop_addr] = value_bytes
|
|
||||||
contents = mem[start_addr:stop_addr]
|
|
||||||
finally:
|
|
||||||
os.close(f)
|
|
@ -17,10 +17,11 @@
|
|||||||
# 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 time
|
import mmap
|
||||||
|
import os
|
||||||
|
|
||||||
import spidev
|
import spidev
|
||||||
from pyfastservo.common import (
|
from 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,
|
||||||
@ -28,69 +29,117 @@ from pyfastservo.common import (
|
|||||||
CTRL_ADDR,
|
CTRL_ADDR,
|
||||||
MAP_MASK,
|
MAP_MASK,
|
||||||
PAGESIZE,
|
PAGESIZE,
|
||||||
write_to_memory,
|
|
||||||
read_from_memory
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# /dev/spidev2.0 <=> spidev<BUS>.<DEVICE>
|
# /dev/spidev2.0 <=> spidev<BUS>.<DEVICE>
|
||||||
MAIN_DAC_BUS = 2
|
MAIN_DAC_BUS = 2
|
||||||
MAIN_DAC_DEVICE = 0
|
MAIN_DAC_DEVICE = 0
|
||||||
|
|
||||||
DAC_VERSION = 0x0A
|
DAC_VERSION = 0x0A
|
||||||
|
|
||||||
|
|
||||||
def spi_write(spi, address, value):
|
def main_dac_init():
|
||||||
spi.xfer2([address, value])
|
spi = spidev.SpiDev()
|
||||||
|
|
||||||
def spi_read(spi, address):
|
try:
|
||||||
rx_buffer = spi.xfer2([0x80 | address, 0x00])
|
spi.open(MAIN_DAC_BUS, MAIN_DAC_DEVICE)
|
||||||
return rx_buffer[1]
|
spi.max_speed_hz = 5000
|
||||||
|
spi.mode = 0b00 # CPOL = 0 CPHA = 0
|
||||||
|
spi.cshigh = True
|
||||||
|
|
||||||
def soft_reset(spi):
|
spi_buffer = [0x00, 0x10] # software reset
|
||||||
spi_write(spi, 0x00, 0x10) # Software reset
|
spi.xfer2(spi_buffer)
|
||||||
spi_write(spi, 0x00, 0x00) # Release software reset
|
|
||||||
spi_read(spi, 0x00) # Read reset address (necessary for reset to take effect)
|
|
||||||
|
|
||||||
def check_version(spi):
|
spi_buffer = [0x00, 0x00] # release software reset
|
||||||
version = spi_read(spi, 0x1F)
|
spi.xfer2(spi_buffer)
|
||||||
print(f"DAC version: 0x{version:02X}")
|
|
||||||
return version == DAC_VERSION
|
|
||||||
|
|
||||||
def configure_dac(spi):
|
spi_buffer = [
|
||||||
power_down_reg = spi_read(spi, 0x01)
|
0x80,
|
||||||
spi_write(spi, 0x01, power_down_reg & ~(1 << 0)) # Clear EXTREF bit for internal reference
|
0x00,
|
||||||
spi_write(spi, 0x0D, 0x00) # Set RREF to 10 kΩ for 1.0V reference
|
] # for some reason it is needed to read the reset address for reset to actually reset
|
||||||
spi_write(spi, 0x04, 0xA0) # Enable on-chip IRSET (1.6 kΩ for 20mA output)
|
rx_buffer = spi.xfer2(spi_buffer)
|
||||||
spi_write(spi, 0x07, 0xA0) # Enable on-chip QRSET (1.6 kΩ for 20mA output)
|
|
||||||
spi_write(spi, 0x05, 0x00) # Disable internal IRCML
|
|
||||||
spi_write(spi, 0x08, 0x00) # Disable internal QRCML
|
|
||||||
spi_write(spi, 0x02, 0xB4) # Enable 2's complement, IFirst: True, IRising: True, DCI_EN: Enabled
|
|
||||||
spi_write(spi, 0x14, 0x00)
|
|
||||||
spi_write(spi, 0x14, 0x08) # Trigger the retimer to reacquire the clock relationship
|
|
||||||
spi_write(spi, 0x14, 0x00)
|
|
||||||
|
|
||||||
def dac_self_calibration(spi):
|
spi_buffer = [0x9F, 0x00] # hardware version
|
||||||
spi_write(spi, 0x12, 0x00) # Reset calibration status
|
rx_buffer = spi.xfer2(spi_buffer)
|
||||||
spi_write(spi, 0x0E, 0x08) # Enable calibration clock, default divide ratio
|
if rx_buffer[1] != DAC_VERSION:
|
||||||
spi_write(spi, 0x0E, 0x38) # CALSELI = 1, CALSELQ = 1, CALCLK = 1
|
print(f"Unrecognized device: 0x{rx_buffer[1]:02X}")
|
||||||
spi_write(spi, 0x12, 0x10) # Set CALEN bit
|
|
||||||
|
|
||||||
while True:
|
print("=== Contents of spi buffer after DAC VERSION read back: ===")
|
||||||
status = spi_read(spi, 0x0F)
|
print(f"0x{rx_buffer[0]:02X}{rx_buffer[1]:02X}")
|
||||||
if status & 0xC0 == 0xC0: # Both CALSTATI and CALSTATQ are 1
|
|
||||||
break
|
spi_buffer = [0x82, 00]
|
||||||
time.sleep(0.01)
|
rx_buffer = spi.xfer2(spi_buffer)
|
||||||
|
print(f"0x{rx_buffer[0]:02X}{rx_buffer[1]:02X}")
|
||||||
|
|
||||||
|
# set to 2's complement and I to be first of pair on data input pads
|
||||||
|
spi_buffer = [0x02, 0xB4]
|
||||||
|
rx_buffer = spi.xfer2(spi_buffer)
|
||||||
|
spi_buffer = [0x82, 00]
|
||||||
|
rx_buffer = spi.xfer2(spi_buffer)
|
||||||
|
print(f"0x{rx_buffer[0]:02X}{rx_buffer[1]:02X}")
|
||||||
|
|
||||||
|
for i in range(10):
|
||||||
|
spi_buffer = [0x94, 0x00]
|
||||||
|
rx_buffer = spi.xfer2(spi_buffer)
|
||||||
|
print(f"0x{rx_buffer[0]:02X}{rx_buffer[1]:02X}")
|
||||||
|
|
||||||
|
finally:
|
||||||
|
spi.close()
|
||||||
|
|
||||||
|
|
||||||
|
def read_from_memory(address, n_bytes):
|
||||||
|
assert n_bytes <= 4
|
||||||
|
addr = address
|
||||||
|
|
||||||
|
try:
|
||||||
|
f = os.open("/dev/mem", os.O_SYNC | os.O_RDWR)
|
||||||
|
with mmap.mmap(
|
||||||
|
f,
|
||||||
|
PAGESIZE,
|
||||||
|
mmap.MAP_SHARED,
|
||||||
|
mmap.PROT_READ | mmap.PROT_WRITE,
|
||||||
|
offset=addr & ~MAP_MASK,
|
||||||
|
) as mem:
|
||||||
|
start_addr = addr & MAP_MASK
|
||||||
|
stop_addr = start_addr + 4
|
||||||
|
# print(f"addr: 0x{addr:x}\tstart_addr: 0x{start_addr}\tstop_addr: 0x{stop_addr}")
|
||||||
|
contents = mem[start_addr:stop_addr]
|
||||||
|
read_value = list(contents)[:n_bytes]
|
||||||
|
finally:
|
||||||
|
os.close(f)
|
||||||
|
|
||||||
|
return read_value
|
||||||
|
|
||||||
|
|
||||||
|
def write_to_memory(address, value):
|
||||||
|
value_bytes = value.to_bytes(4, "little")
|
||||||
|
addr = address
|
||||||
|
|
||||||
|
try:
|
||||||
|
f = os.open("/dev/mem", os.O_SYNC | os.O_RDWR)
|
||||||
|
with mmap.mmap(
|
||||||
|
f,
|
||||||
|
PAGESIZE,
|
||||||
|
mmap.MAP_SHARED,
|
||||||
|
mmap.PROT_READ | mmap.PROT_WRITE,
|
||||||
|
offset=addr & ~MAP_MASK,
|
||||||
|
) as mem:
|
||||||
|
start_addr = addr & MAP_MASK
|
||||||
|
stop_addr = start_addr + 4
|
||||||
|
mem[start_addr:stop_addr] = value_bytes
|
||||||
|
contents = mem[start_addr:stop_addr]
|
||||||
|
finally:
|
||||||
|
os.close(f)
|
||||||
|
|
||||||
spi_write(spi, 0x12, 0x00) # Clear calibration bits
|
|
||||||
spi_write(spi, 0x0E, 0x30) # Keep CALSELI and CALSELQ set, clear CALCLK
|
|
||||||
print("DAC self-calibration completed")
|
|
||||||
|
|
||||||
def manual_override(enable=True):
|
def manual_override(enable=True):
|
||||||
reg_contents = read_from_memory(CTRL_ADDR, 1)[0]
|
reg_contents = read_from_memory(CTRL_ADDR, 1)[0]
|
||||||
|
print(f"REG contents: 0b{reg_contents:03b}")
|
||||||
to_write = reg_contents | 0b1 if enable else reg_contents & 0b110
|
to_write = reg_contents | 0b1 if enable else reg_contents & 0b110
|
||||||
write_to_memory(CTRL_ADDR, to_write)
|
write_to_memory(CTRL_ADDR, to_write)
|
||||||
print(f"Set DAC Output Manual Override: {enable}")
|
|
||||||
|
|
||||||
def power_down_afe(channel, power_down=True):
|
|
||||||
|
def power_down(channel, power_down=True):
|
||||||
assert channel in (0, 1)
|
assert channel in (0, 1)
|
||||||
|
|
||||||
bitmask = 1 << (channel + 1) & 0b111
|
bitmask = 1 << (channel + 1) & 0b111
|
||||||
@ -101,68 +150,33 @@ def power_down_afe(channel, power_down=True):
|
|||||||
to_write = reg_contents | value
|
to_write = reg_contents | value
|
||||||
write_to_memory(CTRL_ADDR, to_write)
|
write_to_memory(CTRL_ADDR, to_write)
|
||||||
reg_contents = read_from_memory(CTRL_ADDR, 1)[0]
|
reg_contents = read_from_memory(CTRL_ADDR, 1)[0]
|
||||||
print(f"Power Down DAC AFE Ch{channel}: {power_down}")
|
print(f"REG contents: 0b{reg_contents:03b}")
|
||||||
|
|
||||||
def set_dac_output(value):
|
|
||||||
value = min(value, 0x3FFF)
|
|
||||||
low_word = value & 0xFF
|
|
||||||
high_word = (value >> 8) & 0x3F
|
|
||||||
|
|
||||||
# Note: DAC HIGH word and LOW word output are not updated
|
def write_sample(channel, sample):
|
||||||
# at the same time. On scope, you will see more than one step
|
assert channel in (0, 1)
|
||||||
# of value changed.
|
if channel == 0:
|
||||||
write_to_memory(CH0_HIGH_WORD_ADDR, high_word)
|
addresses = [CH0_HIGH_WORD_ADDR, CH0_LOW_WORD_ADDR]
|
||||||
write_to_memory(CH0_LOW_WORD_ADDR, low_word)
|
|
||||||
write_to_memory(CH1_HIGH_WORD_ADDR, high_word)
|
|
||||||
write_to_memory(CH1_LOW_WORD_ADDR, low_word)
|
|
||||||
print(f"DAC output set to: 0x{value:04X}")
|
|
||||||
|
|
||||||
def check_clk_relationship(spi):
|
|
||||||
clkmode_reg = spi_read(spi, 0x14)
|
|
||||||
print(f"CLKMODE reg: 0x{clkmode_reg:02X}")
|
|
||||||
if clkmode_reg & 0b00010000:
|
|
||||||
print("Clock relationship is not found")
|
|
||||||
return False
|
|
||||||
else:
|
else:
|
||||||
print("Clock relationship is found")
|
addresses = [CH1_HIGH_WORD_ADDR, CH1_LOW_WORD_ADDR]
|
||||||
return True
|
|
||||||
|
|
||||||
def configure_ad9117():
|
low_word_value = sample & 0xFF
|
||||||
spi = spidev.SpiDev()
|
high_word_value = (sample >> 8) & 0x3F
|
||||||
spi.open(MAIN_DAC_BUS, MAIN_DAC_DEVICE)
|
values = [high_word_value, low_word_value]
|
||||||
spi.max_speed_hz = 5000
|
for addr, value in zip(addresses, values):
|
||||||
spi.mode = 0b00 # CPOL = 0 CPHA = 0
|
write_to_memory(addr, value)
|
||||||
spi.cshigh = False
|
|
||||||
|
|
||||||
try:
|
|
||||||
soft_reset(spi)
|
|
||||||
if not check_version(spi):
|
|
||||||
print("Unrecognized DAC version")
|
|
||||||
return False
|
|
||||||
|
|
||||||
power_down_afe(0, True)
|
def write_ramp():
|
||||||
power_down_afe(1, True)
|
signal = [i for i in range(16384)]
|
||||||
|
|
||||||
configure_dac(spi)
|
for value in signal:
|
||||||
check_clk_relationship(spi)
|
write_sample(0, value)
|
||||||
dac_self_calibration(spi)
|
|
||||||
|
|
||||||
# Enable DAC outputs
|
|
||||||
spi_write(spi, 0x01, spi_read(spi, 0x01) & ~((1 << 4) | (1 << 3)))
|
|
||||||
|
|
||||||
power_down_afe(0, False)
|
|
||||||
power_down_afe(1, False)
|
|
||||||
manual_override(False)
|
|
||||||
|
|
||||||
print("AD9117 configuration completed successfully")
|
|
||||||
return True
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
print(f"Error configuring AD9117: {e}")
|
|
||||||
return False
|
|
||||||
|
|
||||||
finally:
|
|
||||||
spi.close()
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
main_dac_init()
|
||||||
|
power_down(0, False)
|
||||||
|
power_down(1, False)
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
configure_ad9117()
|
main()
|
@ -21,7 +21,7 @@ import mmap
|
|||||||
import os
|
import os
|
||||||
import time
|
import time
|
||||||
|
|
||||||
from pyfastservo.common import (
|
from common import (
|
||||||
LED0_BASE_ADDR,
|
LED0_BASE_ADDR,
|
||||||
LED1_BASE_ADDR,
|
LED1_BASE_ADDR,
|
||||||
LED2_BASE_ADDR,
|
LED2_BASE_ADDR,
|
||||||
|
@ -17,12 +17,14 @@
|
|||||||
# 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/>.
|
||||||
|
|
||||||
from pyfastservo import adc, si5340, dac
|
import adc
|
||||||
|
import si5340
|
||||||
|
import dac
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
si5340.configure_si5340()
|
si5340.configure_si5340()
|
||||||
adc.configure_ltc2195()
|
adc.main()
|
||||||
dac.configure_ad9117()
|
dac.main()
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
@ -17,264 +17,102 @@
|
|||||||
# 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
|
||||||
|
|
||||||
DEVICE_READY = 0x00FE
|
PAGE_ADDR = 0x1
|
||||||
PLL_M_DEN = 0x023B
|
|
||||||
STATUS = 0x000C
|
|
||||||
STATUS_STICKY = 0x0011
|
|
||||||
|
|
||||||
STATUS_LOSREF = 0x04
|
OUT0_MUX_SEL_ADDR = 0x15
|
||||||
STATUS_LOL = 0x08
|
OUT1_MUX_SEL_ADDR = 0x1A
|
||||||
|
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
|
||||||
|
|
||||||
|
|
||||||
def write_register(bus, address, value):
|
N1_DIVIDER_UPDATE_ADDR = 0x17
|
||||||
page = address >> 8
|
|
||||||
register = address & 0xFF
|
|
||||||
bus.write_byte_data(IC_ADDR, 0x01, page)
|
|
||||||
try:
|
|
||||||
bus.write_byte_data(IC_ADDR, register, value)
|
|
||||||
except Exception as e:
|
|
||||||
raise Exception(f"Write failed 0x{value:02X} at 0x{address:04X}: {e}")
|
|
||||||
|
|
||||||
def write_preamble(bus):
|
data_to_write = 0
|
||||||
preamble = [
|
clk_out_addr = [
|
||||||
(0x0B24, 0xC0),
|
OUT0_MUX_SEL_ADDR,
|
||||||
(0x0B25, 0x00),
|
OUT1_MUX_SEL_ADDR,
|
||||||
(0x0502, 0x01),
|
OUT2_MUX_SEL_ADDR,
|
||||||
(0x0505, 0x03),
|
OUT3_MUX_SEL_ADDR,
|
||||||
(0x0957, 0x17),
|
]
|
||||||
(0x0B4E, 0x1A),
|
|
||||||
]
|
|
||||||
for address, value in preamble:
|
|
||||||
write_register(bus, address, value)
|
|
||||||
|
|
||||||
def write_postamble(bus):
|
|
||||||
postamble = [
|
|
||||||
(0x001C, 0x01), # Soft reset
|
|
||||||
(0x0B24, 0xC3),
|
|
||||||
(0x0B25, 0x02),
|
|
||||||
]
|
|
||||||
for address, value in postamble:
|
|
||||||
write_register(bus, 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
|
|
||||||
|
|
||||||
# Programming sequence from ClockBuilder Pro, default settings
|
bus.write_byte_data(IC_ADDR, PAGE_ADDR, 0x0) # setting page to page 0
|
||||||
# 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)
|
|
||||||
|
|
||||||
# PLL Configuration
|
# read device id
|
||||||
(0x0235, 0x00), # M_NUM
|
low_word = bus.read_byte_data(IC_ADDR, 0x2)
|
||||||
(0x0236, 0x00),
|
high_word = bus.read_byte_data(IC_ADDR, 0x3)
|
||||||
(0x0237, 0x00),
|
|
||||||
(0x0238, 0x80),
|
|
||||||
(0x0239, 0x89),
|
|
||||||
(0x023A, 0x00),
|
|
||||||
(0x023B, 0x00), # M_DEN
|
|
||||||
(0x023C, 0x00),
|
|
||||||
(0x023D, 0x00),
|
|
||||||
(0x023E, 0x80),
|
|
||||||
|
|
||||||
# Synthesizer configuration
|
print(f"DEV ID: 0x{high_word:2x}{low_word:2x}")
|
||||||
(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
|
|
||||||
|
|
||||||
# N1 Configuration (1:1 ratio)
|
data_to_write = 0x1
|
||||||
(0x030D, 0x00), # N1_NUM
|
bus.write_byte_data(
|
||||||
(0x030E, 0x00),
|
IC_ADDR, PAGE_ADDR, data_to_write
|
||||||
(0x030F, 0x00),
|
) # change to page 1 for output settings
|
||||||
(0x0310, 0x00),
|
|
||||||
(0x0311, 0x00),
|
|
||||||
(0x0312, 0x01),
|
|
||||||
(0x0313, 0x00), # N1_DEN
|
|
||||||
(0x0314, 0x00),
|
|
||||||
(0x0315, 0x00),
|
|
||||||
(0x0316, 0x01),
|
|
||||||
(0x0317, 0x01), # N1_UPDATE
|
|
||||||
|
|
||||||
# N2 Configuration (1:1 ratio)
|
readback = bus.read_byte_data(IC_ADDR, PAGE_ADDR)
|
||||||
(0x0318, 0x00), # N2_NUM
|
if data_to_write != readback:
|
||||||
(0x0319, 0x00),
|
raise ValueError(f"Failed to set page.")
|
||||||
(0x031A, 0x00),
|
|
||||||
(0x031B, 0x00),
|
|
||||||
(0x031C, 0x00),
|
|
||||||
(0x031D, 0x01),
|
|
||||||
(0x031E, 0x00), # N2_DEN
|
|
||||||
(0x031F, 0x00),
|
|
||||||
(0x0320, 0x00),
|
|
||||||
(0x0321, 0x01),
|
|
||||||
(0x0322, 0x01), # N2_UPDATE
|
|
||||||
|
|
||||||
# N3 Configuration (1:1 ratio)
|
for addr in clk_out_addr:
|
||||||
(0x0323, 0x00), # N3_NUM
|
bus.write_byte_data(IC_ADDR, addr, 1) # set source to N1
|
||||||
(0x0324, 0x00),
|
|
||||||
(0x0325, 0x00),
|
|
||||||
(0x0326, 0x00),
|
|
||||||
(0x0327, 0x00),
|
|
||||||
(0x0328, 0x01),
|
|
||||||
(0x0329, 0x00), # N3_DEN
|
|
||||||
(0x032A, 0x00),
|
|
||||||
(0x032B, 0x00),
|
|
||||||
(0x032C, 0x01),
|
|
||||||
(0x032D, 0x01), # N3_UPDATE
|
|
||||||
|
|
||||||
# Output configuration
|
bus.write_byte_data(IC_ADDR, OUT2_AMPL_ADDR, 13)
|
||||||
(0x0112, 0x06), # OUT0 config
|
readback = bus.read_byte_data(IC_ADDR, OUT2_AMPL_ADDR)
|
||||||
(0x0113, 0x09), # OUT0 format
|
# if data_to_write != readback:
|
||||||
(0x0114, 0x3B), # OUT0 CM/AMPL
|
# raise ValueError(f"Problematic read: {readback}.")
|
||||||
(0x0115, 0x28), # OUT0 MUX_SEL
|
|
||||||
|
|
||||||
(0x0117, 0x06), # OUT1 config
|
bus.write_byte_data(IC_ADDR, OUT2_AMPL_ADDR, 0x6B) # setting OUT2 to LVDS25
|
||||||
(0x0118, 0x09), # OUT1 format
|
|
||||||
(0x0119, 0x3B), # OUT1 CM/AMPL
|
|
||||||
(0x011A, 0x28), # OUT1 MUX_SEL
|
|
||||||
|
|
||||||
(0x0126, 0x06), # OUT2 config
|
bus.write_byte_data(IC_ADDR, OUT3_FORMAT_ADDR, 0xCC) # SETTING out3 to LVCMOS 18
|
||||||
(0x0127, 0x09), # OUT2 format
|
# bus.write_byte_data(IC_ADDR, 0x2E, 0x09) # SETTING out3 to LVCMOS 33
|
||||||
(0x0128, 0x3B), # OUT2 CM/AMPL
|
|
||||||
(0x0129, 0x28), # OUT2 MUX_SEL
|
|
||||||
|
|
||||||
(0x012B, 0x06), # OUT3 config
|
readback = bus.read_byte_data(IC_ADDR, OUT3_PDN_ADDR)
|
||||||
(0x012C, 0xCC), # OUT3 format
|
print(f"Si5340 OUTx_PDN CLK3: 0x{readback}")
|
||||||
(0x012D, 0x00), # OUT3 CM/AMPL
|
|
||||||
(0x012E, 0x58), # OUT3 MUX_SEL
|
|
||||||
|
|
||||||
# Miscellaneous configuration
|
readback = bus.read_byte_data(IC_ADDR, OUT3_FORMAT_ADDR)
|
||||||
(0x090E, 0x02), # XAXB_EXTCLK_EN=0 XAXB_PDNB=1 (use XTAL)
|
print(f"Si5340 OUTx_FORMAT CLK3: 0x{readback}")
|
||||||
(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)
|
|
||||||
]
|
|
||||||
|
|
||||||
write_preamble(bus)
|
readback = bus.read_byte_data(IC_ADDR, OUT3_AMPL_ADDR)
|
||||||
|
print(f"Si5340 OUTx_AMPL CLK3: 0x{readback}")
|
||||||
|
|
||||||
time.sleep(0.3)
|
readback = bus.read_byte_data(IC_ADDR, OUT3_MUX_SEL_ADDR)
|
||||||
|
print(f"Si5340 OUTx_CM CLK3: 0x{readback}")
|
||||||
|
|
||||||
print("Writing main configuration...")
|
bus.write_byte_data(
|
||||||
for address, value in main_config:
|
IC_ADDR, PAGE_ADDR, 0x3
|
||||||
write_register(bus, address, value)
|
) # setting page to 3 to change dividers values
|
||||||
print("Main configuration written")
|
|
||||||
|
|
||||||
write_postamble(bus)
|
n1_numerator = [0x0, 0x0, 0x0, 0x60, 0x22, 0x0]
|
||||||
|
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)
|
||||||
|
|
||||||
if not wait_for_lock(bus):
|
bus.write_byte_data(IC_ADDR, N1_DIVIDER_UPDATE_ADDR, 1)
|
||||||
print("Error waiting for input clock or PLL lock")
|
|
||||||
else:
|
|
||||||
print("Input clock present and PLL locked")
|
|
||||||
|
|
||||||
bus.write_byte_data(IC_ADDR, STATUS_STICKY, 0)
|
for addr in n1_num_addr:
|
||||||
|
readback = bus.read_byte_data(IC_ADDR, addr)
|
||||||
|
print(f"Numerator buffer: 0x{readback:02x}")
|
||||||
|
|
||||||
# Final status check
|
for addr in n1_denom_addr:
|
||||||
pll_locked = check_pll_status(bus)
|
readback = bus.read_byte_data(IC_ADDR, addr)
|
||||||
xaxb_signal_present = check_los_status(bus)
|
print(f"Denominator buffer: 0x{readback:02x}")
|
||||||
|
|
||||||
if not pll_locked:
|
bus.write_byte_data(IC_ADDR, PAGE_ADDR, 0x0) # setting page to page 0
|
||||||
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()
|
22
flake.lock
generated
22
flake.lock
generated
@ -18,16 +18,16 @@
|
|||||||
},
|
},
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1734323986,
|
"lastModified": 1709237383,
|
||||||
"narHash": "sha256-m/lh6hYMIWDYHCAsn81CDAiXoT3gmxXI9J987W5tZrE=",
|
"narHash": "sha256-cy6ArO4k5qTx+l5o+0mL9f5fa86tYUX3ozE1S+Txlds=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "394571358ce82dff7411395829aa6a3aad45b907",
|
"rev": "1536926ef5621b09bba54035ae2bb6d806d72ac8",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"ref": "nixos-24.11",
|
"ref": "nixos-unstable",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
@ -64,11 +64,11 @@
|
|||||||
"src-migen": {
|
"src-migen": {
|
||||||
"flake": false,
|
"flake": false,
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1727677091,
|
"lastModified": 1702942348,
|
||||||
"narHash": "sha256-Zg3SQnTwMM/VkOGKogbPyuCC2NhLy8HB2SPEUWWNgCU=",
|
"narHash": "sha256-gKIfHZxsv+jcgDFRW9mPqmwqbZXuRvXefkZcSFjOGHw=",
|
||||||
"owner": "m-labs",
|
"owner": "m-labs",
|
||||||
"repo": "migen",
|
"repo": "migen",
|
||||||
"rev": "c19ae9f8ae162ffe2d310a92bfce53ac2a821bc8",
|
"rev": "50934ad10a87ade47219b796535978b9bdf24023",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@ -80,11 +80,11 @@
|
|||||||
"src-misoc": {
|
"src-misoc": {
|
||||||
"flake": false,
|
"flake": false,
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1729234629,
|
"lastModified": 1699352904,
|
||||||
"narHash": "sha256-TLsTCXV5AC2xh+bS7EhBVBKqdqIU3eKrnlWcFF9LtAM=",
|
"narHash": "sha256-SglyTmXOPv8jJOjwAjJrj/WhAkItQfUbvKfUqrynwRg=",
|
||||||
"ref": "refs/heads/master",
|
"ref": "refs/heads/master",
|
||||||
"rev": "6085a312bca26adeca6584e37d08c8ba2e1d6e38",
|
"rev": "a53859f2167c31ab5225b6c09f30cf05527b94f4",
|
||||||
"revCount": 2460,
|
"revCount": 2452,
|
||||||
"submodules": true,
|
"submodules": true,
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/m-labs/misoc.git"
|
"url": "https://github.com/m-labs/misoc.git"
|
||||||
|
488
flake.nix
488
flake.nix
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
description = "Firmware for Sinara Fast-Servo based on Not-OS and Linien";
|
description = "Firmware for Sinara Fast-Servo based on Not-OS and Linien";
|
||||||
|
|
||||||
inputs.nixpkgs.url = github:NixOS/nixpkgs/nixos-24.11;
|
inputs.nixpkgs.url = github:NixOS/nixpkgs/nixos-unstable;
|
||||||
inputs.not-os.url = github:cleverca22/not-os;
|
inputs.not-os.url = github:cleverca22/not-os;
|
||||||
inputs.not-os.inputs.nixpkgs.follows = "nixpkgs";
|
inputs.not-os.inputs.nixpkgs.follows = "nixpkgs";
|
||||||
|
|
||||||
@ -10,38 +10,10 @@
|
|||||||
|
|
||||||
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"; };
|
||||||
pkgs-armv7l = pkgs.pkgsCross.zynq-armv7l-linux;
|
not-os-cfg = not-os-configured.config.system;
|
||||||
fsbl-support = ./fast-servo/fsbl-support;
|
fsbl-support = ./fast-servo/fsbl-support;
|
||||||
|
|
||||||
version = "2.1.0";
|
|
||||||
linien-src = pkgs.applyPatches {
|
|
||||||
name = "linien-src";
|
|
||||||
src = pkgs.fetchFromGitHub {
|
|
||||||
owner = "linien-org";
|
|
||||||
repo = "linien";
|
|
||||||
rev = "v" + version;
|
|
||||||
sha256 = "sha256-j6oiP/usLfV5HZtKLcXQ5pHhhxRG05kP2FMwingiWm0=";
|
|
||||||
};
|
|
||||||
prePatch = ''
|
|
||||||
mkdir -p fast_servo/gateware
|
|
||||||
cp -r ${./fast-servo/linien-gateware}/. fast_servo/gateware
|
|
||||||
'';
|
|
||||||
patches = [
|
|
||||||
./fast-servo/linien-common-fast-servo-hardware-specific.patch
|
|
||||||
./fast-servo/linien-server-fast-servo-hardware-specific.patch
|
|
||||||
./fast-servo/linien-gui-fast-servo-hardware-specific.patch
|
|
||||||
./fast-servo/linien-client-ssh-port-change.patch
|
|
||||||
./fast-servo/linien-server-fast-servo.patch
|
|
||||||
./fast-servo/linien-gateware-fast-servo.patch
|
|
||||||
./fast-servo/autolock_pipeline.patch
|
|
||||||
./fast-servo/iir_pipeline.patch
|
|
||||||
./fast-servo/linien_module_pipeline.patch
|
|
||||||
./fast-servo/pid_pipeline.patch
|
|
||||||
./fast-servo/pid_err_sig_pipeline.patch
|
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
patched-not-os = pkgs.applyPatches {
|
patched-not-os = pkgs.applyPatches {
|
||||||
name = "not-os-patched";
|
name = "not-os-patched";
|
||||||
src = not-os;
|
src = not-os;
|
||||||
@ -52,41 +24,9 @@
|
|||||||
./not-os-patches/pr-30.patch
|
./not-os-patches/pr-30.patch
|
||||||
./not-os-patches/pr-31.patch
|
./not-os-patches/pr-31.patch
|
||||||
./not-os-patches/pr-33.patch
|
./not-os-patches/pr-33.patch
|
||||||
./not-os-patches/iproute2.patch
|
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
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: {
|
|
||||||
pkgsCross = super.pkgsCross // {
|
|
||||||
zynq-baremetal = import super.path {
|
|
||||||
system = "x86_64-linux";
|
|
||||||
crossSystem = {
|
|
||||||
config = "arm-none-eabihf";
|
|
||||||
libc = "newlib";
|
|
||||||
gcc.cpu = "cortex-a9";
|
|
||||||
gcc.fpu = "vfpv3";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
zynq-armv7l-linux = import super.path {
|
|
||||||
system = "x86_64-linux";
|
|
||||||
inherit crossSystem;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
migen = pkgs.python3Packages.buildPythonPackage rec {
|
migen = pkgs.python3Packages.buildPythonPackage rec {
|
||||||
name = "migen";
|
name = "migen";
|
||||||
src = src-migen;
|
src = src-migen;
|
||||||
@ -125,209 +65,181 @@
|
|||||||
freetype
|
freetype
|
||||||
fontconfig
|
fontconfig
|
||||||
];
|
];
|
||||||
profile = "set -e; source /opt/Xilinx/Vivado/2024.2/settings64.sh";
|
profile = "set -e; source /opt/Xilinx/Vivado/2022.2/settings64.sh";
|
||||||
runScript = "vivado";
|
runScript = "vivado";
|
||||||
};
|
};
|
||||||
|
|
||||||
cma = pkgs-armv7l.python3Packages.buildPythonPackage rec {
|
pyrp3 = pkgs.python3Packages.buildPythonPackage rec {
|
||||||
pname = "cma";
|
|
||||||
version = "3.3.0";
|
|
||||||
src = pkgs.fetchFromGitHub {
|
|
||||||
owner = "CMA-ES";
|
|
||||||
repo = "pycma";
|
|
||||||
rev = "refs/tags/r${version}";
|
|
||||||
hash = "sha256-+UJI3hDVbDMfRF4bkwHED3eJCHzxS2hO4YPUzJqcoQI=";
|
|
||||||
};
|
|
||||||
|
|
||||||
propagatedBuildInputs = [ pkgs-armv7l.python3Packages.numpy ];
|
|
||||||
|
|
||||||
pythonImportsCheck = [ "cma" ];
|
|
||||||
|
|
||||||
checkPhase = ''
|
|
||||||
# At least one doctest fails, thus only limited amount of files is tested
|
|
||||||
python -m cma.test interfaces.py purecma.py logger.py optimization_tools.py transformations.py
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
pyrp3 = pkgs-armv7l.python3Packages.buildPythonPackage rec {
|
|
||||||
pname = "pyrp3";
|
pname = "pyrp3";
|
||||||
version = "2.1.0";
|
version = "1.2.0";
|
||||||
format = "pyproject";
|
pyproject = true;
|
||||||
src = pkgs.fetchFromGitHub {
|
src = pkgs.fetchFromGitHub {
|
||||||
owner = "linien-org";
|
owner = "linien-org";
|
||||||
repo = "pyrp3";
|
repo = "${pname}";
|
||||||
rev = "v${version}";
|
rev = "v${version}";
|
||||||
hash = "sha256-ol1QGXyCOei94iIPIocuTRHBxa5jKSH5RzjzROfZaBI=";
|
hash = "sha256-43TTlpJ5SMAjQM71bNVvrWQyciRXM3zpuA/Dw41AEgU=";
|
||||||
};
|
};
|
||||||
patches = ./fast-servo/linien-pyrp3-monitor.patch;
|
nativeBuildInputs = with pkgs.python3Packages; [ setuptools wheel setuptools-scm ];
|
||||||
nativeBuildInputs = [
|
propagatedBuildInputs = with pkgs.python3Packages; [
|
||||||
pkgs-armv7l.python3Packages.setuptools
|
myhdl
|
||||||
pkgs-armv7l.gcc
|
rpyc4
|
||||||
];
|
|
||||||
postInstall = ''
|
|
||||||
cp monitor/libmonitor.so $out/lib
|
|
||||||
'';
|
|
||||||
postFixup = ''
|
|
||||||
substituteInPlace $out/${pkgs.python3.sitePackages}/pyrp3/raw_memory.py \
|
|
||||||
--replace "libmonitor.so" "$out/lib/libmonitor.so"
|
|
||||||
'';
|
|
||||||
propagatedBuildInputs = with pkgs-armv7l.python3Packages; [
|
|
||||||
cached-property
|
cached-property
|
||||||
numpy
|
numpy
|
||||||
rpyc
|
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
linien-common = pkgs.python3Packages.buildPythonPackage rec {
|
linien-server = pkgs.python3Packages.buildPythonPackage rec {
|
||||||
pname = "linien-common";
|
pname = "linien-server";
|
||||||
inherit version;
|
|
||||||
pyproject = true;
|
pyproject = true;
|
||||||
|
inherit (pkgs.python3Packages.linien-common) src version;
|
||||||
src = linien-src;
|
sourceRoot = "source/linien-server";
|
||||||
|
|
||||||
sourceRoot = "${src.name}/linien-common";
|
|
||||||
|
|
||||||
preBuild = ''
|
|
||||||
export HOME=$(mktemp -d)
|
|
||||||
'';
|
|
||||||
|
|
||||||
nativeBuildInputs = [ pkgs.python3Packages.setuptools ];
|
nativeBuildInputs = [ pkgs.python3Packages.setuptools ];
|
||||||
|
|
||||||
pythonRelaxDeps = [ "importlib-metadata" ];
|
|
||||||
|
|
||||||
propagatedBuildInputs = with pkgs.python3Packages; [
|
propagatedBuildInputs = with pkgs.python3Packages; [
|
||||||
importlib-metadata
|
|
||||||
numpy
|
|
||||||
rpyc
|
|
||||||
scipy
|
|
||||||
appdirs
|
appdirs
|
||||||
|
certifi
|
||||||
|
click
|
||||||
|
cma
|
||||||
|
pylpsd
|
||||||
|
pyrp3
|
||||||
|
requests
|
||||||
|
linien-common
|
||||||
];
|
];
|
||||||
|
};
|
||||||
|
|
||||||
pythonImportsCheck = [ "linien_common" ];
|
not-os-configured = (import patched-not-os {
|
||||||
|
inherit nixpkgs;
|
||||||
|
extraModules = [
|
||||||
|
"${patched-not-os}/zynq_image.nix"
|
||||||
|
];
|
||||||
|
system = "x86_64-linux";
|
||||||
|
crossSystem.system = "armv7l-linux";
|
||||||
|
});
|
||||||
|
|
||||||
|
gnu-platform = "arm-none-eabi";
|
||||||
|
|
||||||
|
binutils-pkg = { zlib, extraConfigureFlags ? [] }: pkgs.stdenv.mkDerivation rec {
|
||||||
|
basename = "binutils";
|
||||||
|
version = "2.30";
|
||||||
|
name = "${basename}-${gnu-platform}-${version}";
|
||||||
|
src = pkgs.fetchurl {
|
||||||
|
url = "https://ftp.gnu.org/gnu/binutils/binutils-${version}.tar.bz2";
|
||||||
|
sha256 = "028cklfqaab24glva1ks2aqa1zxa6w6xmc8q34zs1sb7h22dxspg";
|
||||||
|
};
|
||||||
|
configureFlags = [
|
||||||
|
"--enable-deterministic-archives"
|
||||||
|
"--target=${gnu-platform}"
|
||||||
|
"--with-cpu=cortex-a9"
|
||||||
|
"--with-fpu=vfpv3"
|
||||||
|
"--with-float=hard"
|
||||||
|
"--with-mode=thumb"
|
||||||
|
] ++ extraConfigureFlags;
|
||||||
|
outputs = [ "out" "info" "man" ];
|
||||||
|
depsBuildBuild = [ pkgs.buildPackages.stdenv.cc ];
|
||||||
|
buildInputs = [ zlib ];
|
||||||
|
enableParallelBuilding = true;
|
||||||
|
meta = {
|
||||||
|
description = "Tools for manipulating binaries (linker, assembler, etc.)";
|
||||||
|
longDescription = ''
|
||||||
|
The GNU Binutils are a collection of binary tools. The main
|
||||||
|
ones are `ld' (the GNU linker) and `as' (the GNU assembler).
|
||||||
|
They also include the BFD (Binary File Descriptor) library,
|
||||||
|
`gprof', `nm', `strip', etc.
|
||||||
|
'';
|
||||||
|
homepage = http://www.gnu.org/software/binutils/;
|
||||||
|
license = pkgs.lib.licenses.gpl3Plus;
|
||||||
|
/* Give binutils a lower priority than gcc-wrapper to prevent a
|
||||||
|
collision due to the ld/as wrappers/symlinks in the latter. */
|
||||||
|
priority = "10";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
gcc-pkg = { gmp, mpfr, libmpc, platform-binutils, extraConfigureFlags ? [] }: pkgs.stdenv.mkDerivation rec {
|
||||||
|
basename = "gcc";
|
||||||
|
version = "9.1.0";
|
||||||
|
name = "${basename}-${gnu-platform}-${version}";
|
||||||
|
src = pkgs.fetchurl {
|
||||||
|
url = "https://ftp.gnu.org/gnu/gcc/gcc-${version}/gcc-${version}.tar.xz";
|
||||||
|
sha256 = "1817nc2bqdc251k0lpc51cimna7v68xjrnvqzvc50q3ax4s6i9kr";
|
||||||
|
};
|
||||||
|
preConfigure = ''
|
||||||
|
mkdir build
|
||||||
|
cd build
|
||||||
|
'';
|
||||||
|
configureScript = "../configure";
|
||||||
|
configureFlags = [
|
||||||
|
"--target=${gnu-platform}"
|
||||||
|
"--with-arch=armv7-a"
|
||||||
|
"--with-tune=cortex-a9"
|
||||||
|
"--with-fpu=vfpv3"
|
||||||
|
"--with-float=hard"
|
||||||
|
"--disable-libssp"
|
||||||
|
"--enable-languages=c"
|
||||||
|
"--with-as=${platform-binutils}/bin/${gnu-platform}-as"
|
||||||
|
"--with-ld=${platform-binutils}/bin/${gnu-platform}-ld" ] ++ extraConfigureFlags;
|
||||||
|
outputs = [ "out" "info" "man" ];
|
||||||
|
hardeningDisable = [ "format" "pie" ];
|
||||||
|
propagatedBuildInputs = [ gmp mpfr libmpc platform-binutils ];
|
||||||
|
enableParallelBuilding = true;
|
||||||
|
dontFixup = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
newlib-pkg = { platform-binutils, platform-gcc }: pkgs.stdenv.mkDerivation rec {
|
||||||
|
pname = "newlib";
|
||||||
|
version = "3.1.0";
|
||||||
|
src = pkgs.fetchurl {
|
||||||
|
url = "ftp://sourceware.org/pub/newlib/newlib-${version}.tar.gz";
|
||||||
|
sha256 = "0ahh3n079zjp7d9wynggwrnrs27440aac04340chf1p9476a2kzv";
|
||||||
|
};
|
||||||
|
nativeBuildInputs = [ platform-binutils platform-gcc ];
|
||||||
|
configureFlags = [
|
||||||
|
"--target=${gnu-platform}"
|
||||||
|
|
||||||
|
"--with-cpu=cortex-a9"
|
||||||
|
"--with-fpu=vfpv3"
|
||||||
|
"--with-float=hard"
|
||||||
|
"--with-mode=thumb"
|
||||||
|
"--enable-interwork"
|
||||||
|
"--disable-multilib"
|
||||||
|
|
||||||
|
"--disable-newlib-supplied-syscalls"
|
||||||
|
"--with-gnu-ld"
|
||||||
|
"--with-gnu-as"
|
||||||
|
"--disable-newlib-io-float"
|
||||||
|
"--disable-werror"
|
||||||
|
];
|
||||||
|
dontFixup = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
linien-common-armv7l = pkgs-armv7l.python3Packages.buildPythonPackage rec {
|
gnutoolchain = rec {
|
||||||
pname = "linien-common-armv7l";
|
binutils-bootstrap = pkgs.callPackage binutils-pkg { };
|
||||||
inherit version;
|
gcc-bootstrap = pkgs.callPackage gcc-pkg {
|
||||||
pyproject = true;
|
platform-binutils = binutils-bootstrap;
|
||||||
|
extraConfigureFlags = [ "--disable-libgcc" ];
|
||||||
src = linien-src;
|
};
|
||||||
|
newlib = pkgs.callPackage newlib-pkg {
|
||||||
sourceRoot = "${src.name}/linien-common";
|
platform-binutils = binutils-bootstrap;
|
||||||
|
platform-gcc = gcc-bootstrap;
|
||||||
preBuild = ''
|
};
|
||||||
export HOME=$(mktemp -d)
|
binutils = pkgs.callPackage binutils-pkg {
|
||||||
'';
|
extraConfigureFlags = [ "--with-lib-path=${newlib}/arm-none-eabi/lib" ];
|
||||||
|
};
|
||||||
nativeBuildInputs = [ pkgs-armv7l.python3Packages.setuptools ];
|
gcc = pkgs.callPackage gcc-pkg {
|
||||||
|
platform-binutils = binutils;
|
||||||
pythonRelaxDeps = [ "importlib-metadata" ];
|
extraConfigureFlags = [ "--enable-newlib" "--with-headers=${newlib}/arm-none-eabi/include" ];
|
||||||
|
|
||||||
propagatedBuildInputs = with pkgs-armv7l.python3Packages; [
|
|
||||||
importlib-metadata
|
|
||||||
numpy
|
|
||||||
rpyc
|
|
||||||
scipy
|
|
||||||
appdirs
|
|
||||||
];
|
|
||||||
|
|
||||||
pythonImportsCheck = [ "linien_common" ];
|
|
||||||
};
|
|
||||||
|
|
||||||
linien-client = pkgs.python3Packages.buildPythonPackage rec {
|
|
||||||
pname = "linien-client";
|
|
||||||
inherit version;
|
|
||||||
src = linien-src;
|
|
||||||
|
|
||||||
pyproject = true;
|
|
||||||
|
|
||||||
sourceRoot = "${src.name}/linien-client";
|
|
||||||
|
|
||||||
preBuild = ''
|
|
||||||
export HOME=$(mktemp -d)
|
|
||||||
'';
|
|
||||||
|
|
||||||
nativeBuildInputs = [ pkgs.python3Packages.setuptools ];
|
|
||||||
|
|
||||||
doInstallCheck = false;
|
|
||||||
doCheck = false;
|
|
||||||
propagatedBuildInputs = with pkgs.python3Packages; [
|
|
||||||
fabric
|
|
||||||
typing-extensions
|
|
||||||
] ++ [ linien-common ];
|
|
||||||
|
|
||||||
pythonImportsCheck = [ "linien_client" ];
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
linien-gui = pkgs.python3Packages.buildPythonApplication rec {
|
|
||||||
pname = "linien-gui";
|
|
||||||
inherit version;
|
|
||||||
src = linien-src;
|
|
||||||
pyproject = true;
|
|
||||||
|
|
||||||
sourceRoot = "${src.name}/linien-gui";
|
|
||||||
nativeBuildInputs = with pkgs.python3Packages; [
|
|
||||||
setuptools
|
|
||||||
] ++ [
|
|
||||||
pkgs.qt5.wrapQtAppsHook
|
|
||||||
];
|
|
||||||
|
|
||||||
patches = [
|
|
||||||
./fast-servo/linien-gui-fast-servo-rm-ota-update.patch
|
|
||||||
];
|
|
||||||
|
|
||||||
# Makes qt-wayland appear in the qt paths injected by the wrapper - helps users
|
|
||||||
# with `QT_QPA_PLATFORM=wayland` in their environment.
|
|
||||||
buildInputs = [
|
|
||||||
pkgs.qt5.qtwayland
|
|
||||||
];
|
|
||||||
|
|
||||||
propagatedBuildInputs = with pkgs.python3Packages; [
|
|
||||||
click
|
|
||||||
pyqtgraph
|
|
||||||
pyqt5
|
|
||||||
requests
|
|
||||||
superqt
|
|
||||||
] ++ [ linien-client ];
|
|
||||||
|
|
||||||
dontWrapQtApps = true;
|
|
||||||
|
|
||||||
preFixup = ''
|
|
||||||
makeWrapperArgs+=("''${qtWrapperArgs[@]}")
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
linien-server = pkgs-armv7l.python3Packages.buildPythonPackage rec {
|
|
||||||
pname = "linien-server";
|
|
||||||
inherit version;
|
|
||||||
src = linien-src;
|
|
||||||
pyproject = true;
|
|
||||||
|
|
||||||
sourceRoot = "${src.name}/linien-server";
|
|
||||||
|
|
||||||
postPatch = ''
|
|
||||||
cp ${fast-servo-gateware}/csrmap.py linien_server/csrmap.py
|
|
||||||
substituteInPlace linien_server/acquisition.py \
|
|
||||||
--replace " start_nginx()" "" \
|
|
||||||
--replace " stop_nginx()" "" \
|
|
||||||
--replace " flash_fpga()" ""
|
|
||||||
'';
|
|
||||||
nativeBuildInputs = [ pkgs-armv7l.python3Packages.setuptools ];
|
|
||||||
propagatedBuildInputs = with pkgs-armv7l.python3Packages; [
|
|
||||||
fire
|
|
||||||
influxdb-client
|
|
||||||
pylpsd
|
|
||||||
] ++ [
|
|
||||||
linien-common-armv7l
|
|
||||||
cma
|
|
||||||
pyrp3
|
|
||||||
];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
fast-servo-gateware = pkgs.stdenv.mkDerivation rec {
|
fast-servo-gateware = pkgs.stdenv.mkDerivation rec {
|
||||||
name = "fast-servo-gateware";
|
name = "fast-servo-gateware";
|
||||||
src = linien-src;
|
inherit (pkgs.python3Packages.linien-common) src;
|
||||||
|
prePatch = ''
|
||||||
|
mkdir -p fast_servo/gateware
|
||||||
|
cp -r ${./fast-servo/linien-gateware}/. fast_servo/gateware
|
||||||
|
'';
|
||||||
|
patches = [
|
||||||
|
fast-servo/linien-fast-servo-gateware.patch
|
||||||
|
fast-servo/linien-fast-servo-server.patch
|
||||||
|
];
|
||||||
nativeBuildInputs = [
|
nativeBuildInputs = [
|
||||||
(pkgs.python3.withPackages(ps: [
|
(pkgs.python3.withPackages(ps: [
|
||||||
migen misoc
|
migen misoc
|
||||||
@ -349,33 +261,11 @@
|
|||||||
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";
|
||||||
@ -400,37 +290,6 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
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 {
|
||||||
@ -440,8 +299,9 @@
|
|||||||
sha256 = "sha256-UDz9KK/Hw3qM1BAeKif30rE8Bi6C2uvuZlvyvtJCMfw=";
|
sha256 = "sha256-UDz9KK/Hw3qM1BAeKif30rE8Bi6C2uvuZlvyvtJCMfw=";
|
||||||
};
|
};
|
||||||
nativeBuildInputs = [
|
nativeBuildInputs = [
|
||||||
pkgs.pkgsCross.zynq-baremetal.buildPackages.binutils
|
pkgs.gnumake
|
||||||
pkgs.pkgsCross.zynq-baremetal.buildPackages.gcc
|
gnutoolchain.binutils
|
||||||
|
gnutoolchain.gcc
|
||||||
];
|
];
|
||||||
postUnpack = ''
|
postUnpack = ''
|
||||||
mkdir -p $sourceRoot/lib/sw_apps/zynq_fsbl/misc/fast-servo
|
mkdir -p $sourceRoot/lib/sw_apps/zynq_fsbl/misc/fast-servo
|
||||||
@ -451,11 +311,7 @@
|
|||||||
patches = [] ++ pkgs.lib.optional (board == "fast-servo") ./fast-servo/fsbl.patch;
|
patches = [] ++ pkgs.lib.optional (board == "fast-servo") ./fast-servo/fsbl.patch;
|
||||||
postPatch = ''
|
postPatch = ''
|
||||||
patchShebangs lib/sw_apps/zynq_fsbl/misc/copy_bsp.sh
|
patchShebangs lib/sw_apps/zynq_fsbl/misc/copy_bsp.sh
|
||||||
|
echo 'SEARCH_DIR("${gnutoolchain.newlib}/arm-none-eabi/lib");' >> lib/sw_apps/zynq_fsbl/src/lscript.ld
|
||||||
for x in lib/sw_apps/zynq_fsbl/src/Makefile lib/sw_apps/zynq_fsbl/misc/copy_bsp.sh lib/bsp/standalone/src/arm/cortexa9/gcc/Makefile; do
|
|
||||||
substituteInPlace $x \
|
|
||||||
--replace "arm-none-eabi-" "arm-none-eabihf-"
|
|
||||||
done
|
|
||||||
'';
|
'';
|
||||||
buildPhase = ''
|
buildPhase = ''
|
||||||
cd lib/sw_apps/zynq_fsbl/src
|
cd lib/sw_apps/zynq_fsbl/src
|
||||||
@ -469,8 +325,9 @@
|
|||||||
dontFixup = true;
|
dontFixup = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
u-boot = (pkgs-armv7l.buildUBoot {
|
u-boot = let
|
||||||
name = "${board}-u-boot";
|
fast-servo-dts = fast-servo/fast-servo.dts;
|
||||||
|
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 = ''
|
||||||
@ -480,7 +337,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-build.toplevel}'
|
setenv bootargs 'root=/dev/mmcblk0p2 console=ttyPS0,115200n8 systemConfig=${builtins.unsafeDiscardStringContext not-os-cfg.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
|
||||||
@ -493,7 +350,7 @@
|
|||||||
filesToInstall = [ "u-boot.elf" ];
|
filesToInstall = [ "u-boot.elf" ];
|
||||||
}).overrideAttrs (oldAttrs: {
|
}).overrideAttrs (oldAttrs: {
|
||||||
postUnpack = ''
|
postUnpack = ''
|
||||||
cp ${fast-servo/fast-servo.dts} $sourceRoot/arch/arm/dts/zynq-fast-servo.dts
|
cp ${fast-servo-dts} $sourceRoot/arch/arm/dts/zynq-fast-servo.dts
|
||||||
'';
|
'';
|
||||||
postInstall = ''
|
postInstall = ''
|
||||||
mkdir -p $out/dts
|
mkdir -p $out/dts
|
||||||
@ -524,7 +381,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 "${board}-dtb"
|
dtb = pkgs.runCommand "dtb"
|
||||||
{
|
{
|
||||||
buildInputs = [ pkgs.gcc pkgs.dtc ];
|
buildInputs = [ pkgs.gcc pkgs.dtc ];
|
||||||
}
|
}
|
||||||
@ -544,14 +401,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-build.toplevel ];
|
storePaths = [ not-os-cfg.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 = "${board}-sd-image";
|
name = "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
|
||||||
@ -585,8 +442,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-build.kernel}/uImage firmware/
|
cp ${not-os-cfg.build.kernel}/uImage firmware/
|
||||||
cp ${not-os-build.uRamdisk}/initrd firmware/uRamdisk.image.gz
|
cp ${not-os-cfg.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
|
||||||
@ -599,9 +456,7 @@
|
|||||||
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
|
||||||
@ -616,7 +471,7 @@
|
|||||||
|
|
||||||
rm -rf $IMGDIR
|
rm -rf $IMGDIR
|
||||||
'';
|
'';
|
||||||
in pkgs.runCommand "${board}-qemu" {
|
in pkgs.runCommand "not-os-qemu" {
|
||||||
inherit qemuScript;
|
inherit qemuScript;
|
||||||
passAsFile = [ "qemuScript" ];
|
passAsFile = [ "qemuScript" ];
|
||||||
preferLocalBuild = true;
|
preferLocalBuild = true;
|
||||||
@ -639,13 +494,6 @@
|
|||||||
"${board}-qemu" = not-os-qemu;
|
"${board}-qemu" = not-os-qemu;
|
||||||
};
|
};
|
||||||
in rec {
|
in rec {
|
||||||
devShell.x86_64-linux = pkgs.mkShell {
|
|
||||||
name = "nix-servo-dev_shell";
|
|
||||||
buildInputs = with pkgs.python3Packages; [
|
|
||||||
matplotlib
|
|
||||||
] ++ [ linien-common linien-client linien-gui ];
|
|
||||||
};
|
|
||||||
|
|
||||||
packages.x86_64-linux = {
|
packages.x86_64-linux = {
|
||||||
inherit mkbootimage;
|
inherit mkbootimage;
|
||||||
inherit migen misoc vivado;
|
inherit migen misoc vivado;
|
||||||
|
@ -1,13 +0,0 @@
|
|||||||
diff --git a/system-path.nix b/system-path.nix
|
|
||||||
index 490197d..93e940a 100644
|
|
||||||
--- a/system-path.nix
|
|
||||||
+++ b/system-path.nix
|
|
||||||
@@ -6,7 +6,7 @@
|
|
||||||
with lib;
|
|
||||||
|
|
||||||
let
|
|
||||||
- requiredPackages = with pkgs; [ utillinux coreutils iproute iputils procps bashInteractive runit ];
|
|
||||||
+ requiredPackages = with pkgs; [ utillinux coreutils iproute2 iputils procps bashInteractive runit ];
|
|
||||||
in
|
|
||||||
{
|
|
||||||
options = {
|
|
@ -1,5 +1,5 @@
|
|||||||
diff --git a/configuration.nix b/configuration.nix
|
diff --git a/configuration.nix b/configuration.nix
|
||||||
index 010c487..2d08009 100644
|
index 010c487..e1e85ba 100644
|
||||||
--- a/configuration.nix
|
--- a/configuration.nix
|
||||||
+++ b/configuration.nix
|
+++ b/configuration.nix
|
||||||
@@ -1,4 +1,4 @@
|
@@ -1,4 +1,4 @@
|
||||||
@ -8,7 +8,7 @@ index 010c487..2d08009 100644
|
|||||||
|
|
||||||
{
|
{
|
||||||
imports = [ ./qemu.nix ];
|
imports = [ ./qemu.nix ];
|
||||||
@@ -7,10 +7,16 @@
|
@@ -7,10 +7,15 @@
|
||||||
environment.etc = {
|
environment.etc = {
|
||||||
"ssh/authorized_keys.d/root" = {
|
"ssh/authorized_keys.d/root" = {
|
||||||
text = ''
|
text = ''
|
||||||
@ -18,7 +18,6 @@ index 010c487..2d08009 100644
|
|||||||
+ ecdsa-sha2-nistp384 AAAAE2VjZHNhLXNoYTItbmlzdHAzODQAAAAIbmlzdHAzODQAAABhBNdIiLvP2hmDUFyyE0oLOIXrjrMdWWpBV9/gPR5m4AiARx4JkufIDZzmptdYQ5FhJORJ4lluPqp7dAmahoSwg4lv9Di0iNQpHMJvNGZLHYKM1H1FWCCFIEDJ8bD4SVfrDg== root
|
+ ecdsa-sha2-nistp384 AAAAE2VjZHNhLXNoYTItbmlzdHAzODQAAAAIbmlzdHAzODQAAABhBNdIiLvP2hmDUFyyE0oLOIXrjrMdWWpBV9/gPR5m4AiARx4JkufIDZzmptdYQ5FhJORJ4lluPqp7dAmahoSwg4lv9Di0iNQpHMJvNGZLHYKM1H1FWCCFIEDJ8bD4SVfrDg== root
|
||||||
+ ecdsa-sha2-nistp384 AAAAE2VjZHNhLXNoYTItbmlzdHAzODQAAAAIbmlzdHAzODQAAABhBF/YybP+fQ0J+bNqM5Vgx5vDmVqVWsgUdF1moUxghv7d73GZAFaM6IFBdrXTAa33AwnWwDPMrTgP1V6SXBkb3ciJo/lD1urJGbydbSI5Ksq9d59wvOeANvyWYrQw6+eqTQ== sb
|
+ ecdsa-sha2-nistp384 AAAAE2VjZHNhLXNoYTItbmlzdHAzODQAAAAIbmlzdHAzODQAAABhBF/YybP+fQ0J+bNqM5Vgx5vDmVqVWsgUdF1moUxghv7d73GZAFaM6IFBdrXTAa33AwnWwDPMrTgP1V6SXBkb3ciJo/lD1urJGbydbSI5Ksq9d59wvOeANvyWYrQw6+eqTQ== sb
|
||||||
+ ecdsa-sha2-nistp384 AAAAE2VjZHNhLXNoYTItbmlzdHAzODQAAAAIbmlzdHAzODQAAABhBFkmOCQ3BQh3qUjLtfdqyeBsx8rkk/QYlzB0TMrnfn6waLN6yKfPC3WVFv4zN5kNKb/OayvqDa+zfkKe85e/oIPQQKflF7GrCHdssz33DCnW90cz532E6iqG1pjeZjID2A== flo
|
+ ecdsa-sha2-nistp384 AAAAE2VjZHNhLXNoYTItbmlzdHAzODQAAAAIbmlzdHAzODQAAABhBFkmOCQ3BQh3qUjLtfdqyeBsx8rkk/QYlzB0TMrnfn6waLN6yKfPC3WVFv4zN5kNKb/OayvqDa+zfkKe85e/oIPQQKflF7GrCHdssz33DCnW90cz532E6iqG1pjeZjID2A== flo
|
||||||
+ ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICAranL376soiSJ0kxdYNrwElcaZPW1heLFjs8Y7n0jT linuswck
|
|
||||||
'';
|
'';
|
||||||
mode = "0444";
|
mode = "0444";
|
||||||
};
|
};
|
||||||
@ -28,15 +27,11 @@ index 010c487..2d08009 100644
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
diff --git a/runit.nix b/runit.nix
|
diff --git a/runit.nix b/runit.nix
|
||||||
index d7b0bf3..14dd437 100644
|
index d7b0bf3..67cff43 100644
|
||||||
--- a/runit.nix
|
--- a/runit.nix
|
||||||
+++ b/runit.nix
|
+++ b/runit.nix
|
||||||
@@ -4,11 +4,11 @@ let
|
@@ -7,8 +7,8 @@ let
|
||||||
sshd_config = pkgs.writeText "sshd_config" ''
|
Port 22
|
||||||
HostKey /etc/ssh/ssh_host_rsa_key
|
|
||||||
HostKey /etc/ssh/ssh_host_ed25519_key
|
|
||||||
- Port 22
|
|
||||||
+ Port 3030
|
|
||||||
PidFile /run/sshd.pid
|
PidFile /run/sshd.pid
|
||||||
Protocol 2
|
Protocol 2
|
||||||
- PermitRootLogin yes
|
- PermitRootLogin yes
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
diff --git a/base.nix b/base.nix
|
diff --git a/base.nix b/base.nix
|
||||||
index 7eaee32..9aa338e 100644
|
index 7eaee32..3a2a0a9 100644
|
||||||
--- a/base.nix
|
--- a/base.nix
|
||||||
+++ b/base.nix
|
+++ b/base.nix
|
||||||
@@ -27,6 +27,11 @@ with lib;
|
@@ -27,6 +27,11 @@ with lib;
|
||||||
@ -14,12 +14,9 @@ index 7eaee32..9aa338e 100644
|
|||||||
not-os.simpleStaticIp = mkOption {
|
not-os.simpleStaticIp = mkOption {
|
||||||
type = types.bool;
|
type = types.bool;
|
||||||
default = false;
|
default = false;
|
||||||
@@ -84,17 +89,25 @@ with lib;
|
@@ -86,15 +91,25 @@ with lib;
|
||||||
};
|
|
||||||
environment.etc = {
|
|
||||||
"nix/nix.conf".source = pkgs.runCommand "nix.conf" {} ''
|
"nix/nix.conf".source = pkgs.runCommand "nix.conf" {} ''
|
||||||
- extraPaths=$(for i in $(cat ${pkgs.writeReferencesToFile pkgs.runtimeShell}); do if test -d $i; then echo $i; fi; done)
|
extraPaths=$(for i in $(cat ${pkgs.writeReferencesToFile pkgs.runtimeShell}); do if test -d $i; then echo $i; fi; done)
|
||||||
+ extraPaths=$(for i in $(cat ${pkgs.writeClosure [ pkgs.bash ]}); do if test -d $i; then echo $i; fi; done)
|
|
||||||
cat > $out << EOF
|
cat > $out << EOF
|
||||||
- build-use-sandbox = true
|
- build-use-sandbox = true
|
||||||
+ auto-optimise-store = true
|
+ auto-optimise-store = true
|
||||||
@ -31,6 +28,8 @@ index 7eaee32..9aa338e 100644
|
|||||||
+ extra-sandbox-paths = /bin/sh=${pkgs.runtimeShell} $(echo $extraPaths)
|
+ extra-sandbox-paths = /bin/sh=${pkgs.runtimeShell} $(echo $extraPaths)
|
||||||
+ max-jobs = auto
|
+ max-jobs = auto
|
||||||
+ sandbox = true
|
+ sandbox = true
|
||||||
|
+ substituters = https://cache.armv7l.xyz
|
||||||
|
+ trusted-public-keys = cache.armv7l.xyz-1:kBY/eGnBAYiqYfg0fy0inWhshUo+pGFM3Pj7kIkmlBk=
|
||||||
+ trusted-users = root
|
+ trusted-users = root
|
||||||
EOF
|
EOF
|
||||||
'';
|
'';
|
||||||
@ -152,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..069fe89 100644
|
index 3fa23ab..e2e3871 100644
|
||||||
--- a/zynq_image.nix
|
--- a/zynq_image.nix
|
||||||
+++ b/zynq_image.nix
|
+++ b/zynq_image.nix
|
||||||
@@ -1,66 +1,89 @@
|
@@ -1,66 +1,102 @@
|
||||||
-{ config, pkgs, ... }:
|
-{ config, pkgs, ... }:
|
||||||
+{ lib, config, pkgs, ... }:
|
+{ lib, config, pkgs, ... }:
|
||||||
|
|
||||||
@ -164,7 +163,22 @@ index 3fa23ab..069fe89 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 {
|
||||||
+ customKernel = (pkgs.linux_6_6.override {
|
+ crosspkgs = import pkgs.path {
|
||||||
|
+ 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
|
||||||
@ -181,15 +195,14 @@ index 3fa23ab..069fe89 100644
|
|||||||
+ OF_OVERLAY y
|
+ OF_OVERLAY y
|
||||||
'';
|
'';
|
||||||
- };
|
- };
|
||||||
|
- customKernelPackages = pkgs.linuxPackagesFor customKernel;
|
||||||
+ }).overrideAttrs (oa: {
|
+ }).overrideAttrs (oa: {
|
||||||
+ postInstall = ''
|
+ postInstall = ''
|
||||||
+ if [ -e arch/arm/boot/uImage ]; then
|
+ cp arch/arm/boot/uImage $out
|
||||||
+ cp arch/arm/boot/uImage $out
|
|
||||||
+ fi
|
|
||||||
+ ${oa.postInstall}
|
+ ${oa.postInstall}
|
||||||
+ '';
|
+ '';
|
||||||
+ });
|
+ });
|
||||||
customKernelPackages = pkgs.linuxPackagesFor customKernel;
|
+ customKernelPackages = crosspkgs.linuxPackagesFor customKernel;
|
||||||
in {
|
in {
|
||||||
imports = [ ./arm32-cross-fixes.nix ];
|
imports = [ ./arm32-cross-fixes.nix ];
|
||||||
boot.kernelPackages = customKernelPackages;
|
boot.kernelPackages = customKernelPackages;
|
||||||
@ -240,17 +253,17 @@ index 3fa23ab..069fe89 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
|
||||||
+ environment = {
|
+ environment = {
|
||||||
+ systemPackages = with pkgs; [ inetutils wget gnugrep nano vim ];
|
+ systemPackages = with pkgs; [ inetutils wget nano ];
|
||||||
+ etc = {
|
+ etc = {
|
||||||
+ "service/getty/run".source = pkgs.writeShellScript "getty" ''
|
+ "service/getty/run".source = pkgs.writeShellScript "getty" ''
|
||||||
+ hostname ${config.networking.hostName}
|
+ hostname ${config.networking.hostName}
|
||||||
|
@ -394,10 +394,10 @@ index 0000000..53c5349
|
|||||||
\ No newline at end of file
|
\ No newline at end of file
|
||||||
diff --git a/xilinx-fpga-manager.patch b/xilinx-fpga-manager.patch
|
diff --git a/xilinx-fpga-manager.patch b/xilinx-fpga-manager.patch
|
||||||
new file mode 100644
|
new file mode 100644
|
||||||
index 0000000..33daffe
|
index 0000000..59aa585
|
||||||
--- /dev/null
|
--- /dev/null
|
||||||
+++ b/xilinx-fpga-manager.patch
|
+++ b/xilinx-fpga-manager.patch
|
||||||
@@ -0,0 +1,676 @@
|
@@ -0,0 +1,663 @@
|
||||||
+# Enable user-space interface for PL programming via Linux FPGA manager
|
+# Enable user-space interface for PL programming via Linux FPGA manager
|
||||||
+# diff cherry-picked from Xilinx/linux-xilinx/tree/xlnx_rebase_v6.6_LTS
|
+# diff cherry-picked from Xilinx/linux-xilinx/tree/xlnx_rebase_v6.6_LTS
|
||||||
+# commit IDs: e61c0a9, 0a38712, dc67651, 89a24e3, 8d224b1, 2a9c05f, 4e94580
|
+# commit IDs: e61c0a9, 0a38712, dc67651, 89a24e3, 8d224b1, 2a9c05f, 4e94580
|
||||||
@ -425,7 +425,7 @@ index 0000000..33daffe
|
|||||||
+ tristate "Altera SOCFPGA FPGA Manager"
|
+ tristate "Altera SOCFPGA FPGA Manager"
|
||||||
+ depends on ARCH_INTEL_SOCFPGA || COMPILE_TEST
|
+ depends on ARCH_INTEL_SOCFPGA || COMPILE_TEST
|
||||||
+diff --git a/drivers/fpga/fpga-mgr.c b/drivers/fpga/fpga-mgr.c
|
+diff --git a/drivers/fpga/fpga-mgr.c b/drivers/fpga/fpga-mgr.c
|
||||||
+index 0f4035b089a2..3aa9f5f041f6 100644
|
+index 06651389c592..6e8c45974f28 100644
|
||||||
+--- a/drivers/fpga/fpga-mgr.c
|
+--- a/drivers/fpga/fpga-mgr.c
|
||||||
++++ b/drivers/fpga/fpga-mgr.c
|
++++ b/drivers/fpga/fpga-mgr.c
|
||||||
+@@ -8,6 +8,9 @@
|
+@@ -8,6 +8,9 @@
|
||||||
@ -673,7 +673,7 @@ index 0000000..33daffe
|
|||||||
+ NULL,
|
+ NULL,
|
||||||
+ };
|
+ };
|
||||||
+ ATTRIBUTE_GROUPS(fpga_mgr);
|
+ ATTRIBUTE_GROUPS(fpga_mgr);
|
||||||
+@@ -739,6 +871,106 @@ void fpga_mgr_put(struct fpga_manager *mgr)
|
+@@ -732,6 +864,106 @@ void fpga_mgr_put(struct fpga_manager *mgr)
|
||||||
+ }
|
+ }
|
||||||
+ EXPORT_SYMBOL_GPL(fpga_mgr_put);
|
+ EXPORT_SYMBOL_GPL(fpga_mgr_put);
|
||||||
+
|
+
|
||||||
@ -780,8 +780,8 @@ index 0000000..33daffe
|
|||||||
+ /**
|
+ /**
|
||||||
+ * fpga_mgr_lock - Lock FPGA manager for exclusive use
|
+ * fpga_mgr_lock - Lock FPGA manager for exclusive use
|
||||||
+ * @mgr: fpga manager
|
+ * @mgr: fpga manager
|
||||||
+@@ -788,6 +1020,9 @@ __fpga_mgr_register_full(struct device *parent, const struct fpga_manager_info *
|
+@@ -779,6 +1011,9 @@ struct fpga_manager *
|
||||||
+ struct module *owner)
|
+ fpga_mgr_register_full(struct device *parent, const struct fpga_manager_info *info)
|
||||||
+ {
|
+ {
|
||||||
+ const struct fpga_manager_ops *mops = info->mops;
|
+ const struct fpga_manager_ops *mops = info->mops;
|
||||||
++#ifdef CONFIG_FPGA_MGR_DEBUG_FS
|
++#ifdef CONFIG_FPGA_MGR_DEBUG_FS
|
||||||
@ -790,7 +790,7 @@ index 0000000..33daffe
|
|||||||
+ struct fpga_manager *mgr;
|
+ struct fpga_manager *mgr;
|
||||||
+ int id, ret;
|
+ int id, ret;
|
||||||
+
|
+
|
||||||
+@@ -826,10 +1061,28 @@ __fpga_mgr_register_full(struct device *parent, const struct fpga_manager_info *
|
+@@ -815,10 +1050,28 @@ fpga_mgr_register_full(struct device *parent, const struct fpga_manager_info *in
|
||||||
+ mgr->dev.of_node = parent->of_node;
|
+ mgr->dev.of_node = parent->of_node;
|
||||||
+ mgr->dev.id = id;
|
+ mgr->dev.id = id;
|
||||||
+
|
+
|
||||||
@ -819,7 +819,7 @@ index 0000000..33daffe
|
|||||||
+ /*
|
+ /*
|
||||||
+ * Initialize framework state by requesting low level driver read state
|
+ * Initialize framework state by requesting low level driver read state
|
||||||
+ * from device. FPGA may be in reset mode or may have been programmed
|
+ * from device. FPGA may be in reset mode or may have been programmed
|
||||||
+@@ -843,6 +1096,28 @@ __fpga_mgr_register_full(struct device *parent, const struct fpga_manager_info *
|
+@@ -832,6 +1085,28 @@ fpga_mgr_register_full(struct device *parent, const struct fpga_manager_info *in
|
||||||
+ return ERR_PTR(ret);
|
+ return ERR_PTR(ret);
|
||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
@ -848,7 +848,7 @@ index 0000000..33daffe
|
|||||||
+ return mgr;
|
+ return mgr;
|
||||||
+
|
+
|
||||||
+ error_device:
|
+ error_device:
|
||||||
+@@ -894,6 +1169,10 @@ void fpga_mgr_unregister(struct fpga_manager *mgr)
|
+@@ -882,6 +1157,10 @@ void fpga_mgr_unregister(struct fpga_manager *mgr)
|
||||||
+ {
|
+ {
|
||||||
+ dev_info(&mgr->dev, "%s %s\n", __func__, mgr->name);
|
+ dev_info(&mgr->dev, "%s %s\n", __func__, mgr->name);
|
||||||
+
|
+
|
||||||
@ -881,10 +881,10 @@ index 0000000..33daffe
|
|||||||
+ &firmware_name)) {
|
+ &firmware_name)) {
|
||||||
+ info->firmware_name = devm_kstrdup(dev, firmware_name,
|
+ info->firmware_name = devm_kstrdup(dev, firmware_name,
|
||||||
+diff --git a/drivers/fpga/zynqmp-fpga.c b/drivers/fpga/zynqmp-fpga.c
|
+diff --git a/drivers/fpga/zynqmp-fpga.c b/drivers/fpga/zynqmp-fpga.c
|
||||||
+index f3434e2c487b..d2434ed85eff 100644
|
+index f3434e2c487b..db923746cac5 100644
|
||||||
+--- a/drivers/fpga/zynqmp-fpga.c
|
+--- a/drivers/fpga/zynqmp-fpga.c
|
||||||
++++ b/drivers/fpga/zynqmp-fpga.c
|
++++ b/drivers/fpga/zynqmp-fpga.c
|
||||||
+@@ -43,25 +43,47 @@ static int zynqmp_fpga_ops_write(struct fpga_manager *mgr,
|
+@@ -43,25 +43,42 @@ static int zynqmp_fpga_ops_write(struct fpga_manager *mgr,
|
||||||
+ struct zynqmp_fpga_priv *priv;
|
+ struct zynqmp_fpga_priv *priv;
|
||||||
+ dma_addr_t dma_addr;
|
+ dma_addr_t dma_addr;
|
||||||
+ u32 eemi_flags = 0;
|
+ u32 eemi_flags = 0;
|
||||||
@ -915,11 +915,6 @@ index 0000000..33daffe
|
|||||||
++
|
++
|
||||||
+ wmb(); /* ensure all writes are done before initiate FW call */
|
+ wmb(); /* ensure all writes are done before initiate FW call */
|
||||||
+
|
+
|
||||||
++ if (priv->flags & FPGA_MGR_DDR_MEM_AUTH_BITSTREAM)
|
|
||||||
++ eemi_flags |= XILINX_ZYNQMP_PM_FPGA_AUTHENTICATION_DDR;
|
|
||||||
++ else if (priv->flags & FPGA_MGR_SECURE_MEM_AUTH_BITSTREAM)
|
|
||||||
++ eemi_flags |= XILINX_ZYNQMP_PM_FPGA_AUTHENTICATION_OCM;
|
|
||||||
++
|
|
||||||
+ if (priv->flags & FPGA_MGR_PARTIAL_RECONFIG)
|
+ if (priv->flags & FPGA_MGR_PARTIAL_RECONFIG)
|
||||||
+ eemi_flags |= XILINX_ZYNQMP_PM_FPGA_PARTIAL;
|
+ eemi_flags |= XILINX_ZYNQMP_PM_FPGA_PARTIAL;
|
||||||
+
|
+
|
||||||
@ -936,22 +931,20 @@ index 0000000..33daffe
|
|||||||
+ return ret;
|
+ return ret;
|
||||||
+ }
|
+ }
|
||||||
+diff --git a/include/linux/firmware/xlnx-zynqmp.h b/include/linux/firmware/xlnx-zynqmp.h
|
+diff --git a/include/linux/firmware/xlnx-zynqmp.h b/include/linux/firmware/xlnx-zynqmp.h
|
||||||
+index e8b12ec8b060..ffd2dfdb6abd 100644
|
+index 9dda7d9898ff..edaf77160746 100644
|
||||||
+--- a/include/linux/firmware/xlnx-zynqmp.h
|
+--- a/include/linux/firmware/xlnx-zynqmp.h
|
||||||
++++ b/include/linux/firmware/xlnx-zynqmp.h
|
++++ b/include/linux/firmware/xlnx-zynqmp.h
|
||||||
+@@ -83,6 +83,10 @@
|
+@@ -70,6 +70,8 @@
|
||||||
+ */
|
+ */
|
||||||
+ #define XILINX_ZYNQMP_PM_FPGA_FULL 0x0U
|
+ #define XILINX_ZYNQMP_PM_FPGA_FULL 0x0U
|
||||||
+ #define XILINX_ZYNQMP_PM_FPGA_PARTIAL BIT(0)
|
+ #define XILINX_ZYNQMP_PM_FPGA_PARTIAL BIT(0)
|
||||||
++#define XILINX_ZYNQMP_PM_FPGA_AUTHENTICATION_DDR BIT(1)
|
|
||||||
++#define XILINX_ZYNQMP_PM_FPGA_AUTHENTICATION_OCM BIT(2)
|
|
||||||
++#define XILINX_ZYNQMP_PM_FPGA_ENCRYPTION_USERKEY BIT(3)
|
++#define XILINX_ZYNQMP_PM_FPGA_ENCRYPTION_USERKEY BIT(3)
|
||||||
++#define XILINX_ZYNQMP_PM_FPGA_ENCRYPTION_DEVKEY BIT(4)
|
++#define XILINX_ZYNQMP_PM_FPGA_ENCRYPTION_DEVKEY BIT(4)
|
||||||
+
|
+
|
||||||
+ /* FPGA Status Reg */
|
+ /* FPGA Status Reg */
|
||||||
+ #define XILINX_ZYNQMP_PM_FPGA_CONFIG_STAT_OFFSET 7U
|
+ #define XILINX_ZYNQMP_PM_FPGA_CONFIG_STAT_OFFSET 7U
|
||||||
+diff --git a/include/linux/fpga/fpga-mgr.h b/include/linux/fpga/fpga-mgr.h
|
+diff --git a/include/linux/fpga/fpga-mgr.h b/include/linux/fpga/fpga-mgr.h
|
||||||
+index 0d4fe068f3d8..f884d268c974 100644
|
+index 54f63459efd6..c96a4405f909 100644
|
||||||
+--- a/include/linux/fpga/fpga-mgr.h
|
+--- a/include/linux/fpga/fpga-mgr.h
|
||||||
++++ b/include/linux/fpga/fpga-mgr.h
|
++++ b/include/linux/fpga/fpga-mgr.h
|
||||||
+@@ -9,8 +9,11 @@
|
+@@ -9,8 +9,11 @@
|
||||||
@ -966,7 +959,7 @@ index 0000000..33daffe
|
|||||||
+ struct fpga_manager;
|
+ struct fpga_manager;
|
||||||
+ struct sg_table;
|
+ struct sg_table;
|
||||||
+
|
+
|
||||||
+@@ -66,17 +69,29 @@ enum fpga_mgr_states {
|
+@@ -66,17 +69,25 @@ enum fpga_mgr_states {
|
||||||
+ *
|
+ *
|
||||||
+ * %FPGA_MGR_EXTERNAL_CONFIG: FPGA has been configured prior to Linux booting
|
+ * %FPGA_MGR_EXTERNAL_CONFIG: FPGA has been configured prior to Linux booting
|
||||||
+ *
|
+ *
|
||||||
@ -980,10 +973,6 @@ index 0000000..33daffe
|
|||||||
++ *
|
++ *
|
||||||
++ * %FPGA_MGR_USERKEY_ENCRYPTED_BITSTREAM: indicates bitstream is encrypted with
|
++ * %FPGA_MGR_USERKEY_ENCRYPTED_BITSTREAM: indicates bitstream is encrypted with
|
||||||
++ * user key
|
++ * user key
|
||||||
++ * %FPGA_MGR_DDR_MEM_AUTH_BITSTREAM: do bitstream authentication using DDR
|
|
||||||
++ * memory if supported
|
|
||||||
++ * %FPGA_MGR_SECURE_MEM_AUTH_BITSTREAM: do bitstream authentication using secure
|
|
||||||
++ * memory if supported
|
|
||||||
+ */
|
+ */
|
||||||
+ #define FPGA_MGR_PARTIAL_RECONFIG BIT(0)
|
+ #define FPGA_MGR_PARTIAL_RECONFIG BIT(0)
|
||||||
+ #define FPGA_MGR_EXTERNAL_CONFIG BIT(1)
|
+ #define FPGA_MGR_EXTERNAL_CONFIG BIT(1)
|
||||||
@ -997,7 +986,7 @@ index 0000000..33daffe
|
|||||||
+
|
+
|
||||||
+ /**
|
+ /**
|
||||||
+ * struct fpga_image_info - information specific to an FPGA image
|
+ * struct fpga_image_info - information specific to an FPGA image
|
||||||
+@@ -86,6 +101,7 @@ enum fpga_mgr_states {
|
+@@ -86,6 +97,7 @@ enum fpga_mgr_states {
|
||||||
+ * @config_complete_timeout_us: maximum time for FPGA to switch to operating
|
+ * @config_complete_timeout_us: maximum time for FPGA to switch to operating
|
||||||
+ * status in the write_complete op.
|
+ * status in the write_complete op.
|
||||||
+ * @firmware_name: name of FPGA image firmware file
|
+ * @firmware_name: name of FPGA image firmware file
|
||||||
@ -1005,7 +994,7 @@ index 0000000..33daffe
|
|||||||
+ * @sgt: scatter/gather table containing FPGA image
|
+ * @sgt: scatter/gather table containing FPGA image
|
||||||
+ * @buf: contiguous buffer containing FPGA image
|
+ * @buf: contiguous buffer containing FPGA image
|
||||||
+ * @count: size of buf
|
+ * @count: size of buf
|
||||||
+@@ -102,6 +118,7 @@ struct fpga_image_info {
|
+@@ -102,6 +114,7 @@ struct fpga_image_info {
|
||||||
+ u32 disable_timeout_us;
|
+ u32 disable_timeout_us;
|
||||||
+ u32 config_complete_timeout_us;
|
+ u32 config_complete_timeout_us;
|
||||||
+ char *firmware_name;
|
+ char *firmware_name;
|
||||||
@ -1013,7 +1002,7 @@ index 0000000..33daffe
|
|||||||
+ struct sg_table *sgt;
|
+ struct sg_table *sgt;
|
||||||
+ const char *buf;
|
+ const char *buf;
|
||||||
+ size_t count;
|
+ size_t count;
|
||||||
+@@ -160,6 +177,7 @@ struct fpga_manager_info {
|
+@@ -160,6 +173,7 @@ struct fpga_manager_info {
|
||||||
+ * @write: write count bytes of configuration data to the FPGA
|
+ * @write: write count bytes of configuration data to the FPGA
|
||||||
+ * @write_sg: write the scatter list of configuration data to the FPGA
|
+ * @write_sg: write the scatter list of configuration data to the FPGA
|
||||||
+ * @write_complete: set FPGA to operating state after writing is done
|
+ * @write_complete: set FPGA to operating state after writing is done
|
||||||
@ -1021,7 +1010,7 @@ index 0000000..33daffe
|
|||||||
+ * @fpga_remove: optional: Set FPGA into a specific state during driver remove
|
+ * @fpga_remove: optional: Set FPGA into a specific state during driver remove
|
||||||
+ * @groups: optional attribute groups.
|
+ * @groups: optional attribute groups.
|
||||||
+ *
|
+ *
|
||||||
+@@ -182,6 +200,7 @@ struct fpga_manager_ops {
|
+@@ -182,6 +196,7 @@ struct fpga_manager_ops {
|
||||||
+ int (*write_sg)(struct fpga_manager *mgr, struct sg_table *sgt);
|
+ int (*write_sg)(struct fpga_manager *mgr, struct sg_table *sgt);
|
||||||
+ int (*write_complete)(struct fpga_manager *mgr,
|
+ int (*write_complete)(struct fpga_manager *mgr,
|
||||||
+ struct fpga_image_info *info);
|
+ struct fpga_image_info *info);
|
||||||
@ -1029,7 +1018,7 @@ index 0000000..33daffe
|
|||||||
+ void (*fpga_remove)(struct fpga_manager *mgr);
|
+ void (*fpga_remove)(struct fpga_manager *mgr);
|
||||||
+ const struct attribute_group **groups;
|
+ const struct attribute_group **groups;
|
||||||
+ };
|
+ };
|
||||||
+@@ -196,23 +215,37 @@ struct fpga_manager_ops {
|
+@@ -196,21 +211,35 @@ struct fpga_manager_ops {
|
||||||
+ /**
|
+ /**
|
||||||
+ * struct fpga_manager - fpga manager structure
|
+ * struct fpga_manager - fpga manager structure
|
||||||
+ * @name: name of low level fpga manager
|
+ * @name: name of low level fpga manager
|
||||||
@ -1042,7 +1031,6 @@ index 0000000..33daffe
|
|||||||
+ * @state: state of fpga manager
|
+ * @state: state of fpga manager
|
||||||
+ * @compat_id: FPGA manager id for compatibility check.
|
+ * @compat_id: FPGA manager id for compatibility check.
|
||||||
+ * @mops: pointer to struct of fpga manager ops
|
+ * @mops: pointer to struct of fpga manager ops
|
||||||
+ * @mops_owner: module containing the mops
|
|
||||||
+ * @priv: low level driver private date
|
+ * @priv: low level driver private date
|
||||||
++ * @err: low level driver error code
|
++ * @err: low level driver error code
|
||||||
++ * @dir: debugfs image directory
|
++ * @dir: debugfs image directory
|
||||||
@ -1058,7 +1046,6 @@ index 0000000..33daffe
|
|||||||
+ enum fpga_mgr_states state;
|
+ enum fpga_mgr_states state;
|
||||||
+ struct fpga_compat_id *compat_id;
|
+ struct fpga_compat_id *compat_id;
|
||||||
+ const struct fpga_manager_ops *mops;
|
+ const struct fpga_manager_ops *mops;
|
||||||
+ struct module *mops_owner;
|
|
||||||
+ void *priv;
|
+ void *priv;
|
||||||
++ int err;
|
++ int err;
|
||||||
++#ifdef CONFIG_FPGA_MGR_DEBUG_FS
|
++#ifdef CONFIG_FPGA_MGR_DEBUG_FS
|
||||||
@ -1067,21 +1054,21 @@ index 0000000..33daffe
|
|||||||
+ };
|
+ };
|
||||||
+
|
+
|
||||||
+ #define to_fpga_manager(d) container_of(d, struct fpga_manager, dev)
|
+ #define to_fpga_manager(d) container_of(d, struct fpga_manager, dev)
|
||||||
+@@ -258,4 +291,6 @@ __devm_fpga_mgr_register(struct device *parent, const char *name,
|
+@@ -244,4 +273,6 @@ struct fpga_manager *
|
||||||
+ const struct fpga_manager_ops *mops, void *priv,
|
+ devm_fpga_mgr_register(struct device *parent, const char *name,
|
||||||
+ struct module *owner);
|
+ const struct fpga_manager_ops *mops, void *priv);
|
||||||
+
|
+
|
||||||
++#define FPGA_IOCTL_LOAD_DMA_BUFF _IOWR('R', 1, __u32)
|
++#define FPGA_IOCTL_LOAD_DMA_BUFF _IOWR('R', 1, __u32)
|
||||||
++
|
++
|
||||||
+ #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 d5c5eda..7ede584 100644
|
index e2e3871..2decd54 100644
|
||||||
--- a/zynq_image.nix
|
--- a/zynq_image.nix
|
||||||
+++ b/zynq_image.nix
|
+++ b/zynq_image.nix
|
||||||
@@ -3,6 +3,16 @@
|
@@ -18,6 +18,16 @@ let
|
||||||
with lib;
|
};
|
||||||
let
|
};
|
||||||
customKernel = (pkgs.linux_6_6.override {
|
customKernel = (crosspkgs.linux.override {
|
||||||
+ kernelPatches = [
|
+ kernelPatches = [
|
||||||
+ ({
|
+ ({
|
||||||
+ name = "xilinx-configfs-overlays";
|
+ name = "xilinx-configfs-overlays";
|
||||||
@ -1095,7 +1082,7 @@ index d5c5eda..7ede584 100644
|
|||||||
extraConfig = ''
|
extraConfig = ''
|
||||||
OVERLAY_FS y
|
OVERLAY_FS y
|
||||||
MEDIA_SUPPORT n
|
MEDIA_SUPPORT n
|
||||||
@@ -17,6 +27,7 @@ let
|
@@ -32,6 +42,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
|
||||||
|
Loading…
Reference in New Issue
Block a user