Compare commits
4 Commits
ec506fd0ce
...
3ec537a5da
Author | SHA1 | Date |
---|---|---|
morgan | 3ec537a5da | |
morgan | 142e01a98c | |
morgan | ee198c5396 | |
morgan | f879a44f05 |
|
@ -563,10 +563,7 @@ class GenericSatellite(SoCCore):
|
|||
self.csr_devices.append("main_dcxo")
|
||||
self.csr_devices.append("helper_dcxo")
|
||||
self.csr_devices.append("wrpll")
|
||||
self.comb += [
|
||||
self.ps7.interrupt[0].eq(self.wrpll.gtx_tag_ev.irq), # IRQ_ID = 61
|
||||
self.ps7.interrupt[1].eq(self.wrpll.main_tag_ev.irq) # IRQ_ID = 62
|
||||
]
|
||||
self.comb += self.ps7.core.core0.nfiq.eq(self.wrpll.ev.irq)
|
||||
self.config["HAS_SI549"] = None
|
||||
else:
|
||||
self.submodules.siphaser = SiPhaser7Series(
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
from migen import *
|
||||
from migen.genlib.fsm import *
|
||||
from migen.genlib.cdc import MultiReg, PulseSynchronizer, BlindTransfer
|
||||
|
||||
from misoc.interconnect.csr import *
|
||||
|
||||
|
@ -37,7 +36,7 @@ class I2CMasterMachine(Module):
|
|||
self.data = Signal(8)
|
||||
self.ready = Signal()
|
||||
|
||||
###
|
||||
# # #
|
||||
|
||||
bits = Signal(4)
|
||||
data = Signal(8)
|
||||
|
@ -136,9 +135,6 @@ class ADPLLProgrammer(Module):
|
|||
self.sda_i = Signal()
|
||||
self.sda_o = Signal()
|
||||
|
||||
self.scl.attr.add("no_retiming")
|
||||
self.sda_o.attr.add("no_retiming")
|
||||
|
||||
# # #
|
||||
|
||||
master = I2CMasterMachine(16)
|
||||
|
@ -228,82 +224,55 @@ class ADPLLProgrammer(Module):
|
|||
|
||||
class Si549(Module, AutoCSR):
|
||||
def __init__(self, pads):
|
||||
# switching sys clk will reset all csr values
|
||||
self.bitbang_enable = CSRStorage()
|
||||
self.gpio_in = CSRStatus(2)
|
||||
self.gpio_out = CSRStorage(2)
|
||||
self.gpio_oe = CSRStorage(2)
|
||||
|
||||
self.i2c_divider = CSRStorage(16, reset=75)
|
||||
self.i2c_address = CSRStorage(7)
|
||||
self.nack = CSRStatus()
|
||||
|
||||
self.adpll = CSRStorage(24)
|
||||
self.adpll_stb = CSRStorage()
|
||||
self.adpll_busy = CSRStatus()
|
||||
self.nack = CSRStatus()
|
||||
|
||||
self.bitbang_enable = CSRStorage()
|
||||
|
||||
self.sda_oe = CSRStorage()
|
||||
self.sda_out = CSRStorage()
|
||||
self.sda_in = CSRStatus()
|
||||
self.scl_oe = CSRStorage()
|
||||
self.scl_out = CSRStorage()
|
||||
|
||||
# # #
|
||||
|
||||
self.submodules.programmer = ClockDomainsRenamer("helper")(ADPLLProgrammer())
|
||||
self.submodules.programmer = ADPLLProgrammer()
|
||||
|
||||
self.i2c_divider.storage.attr.add("no_retiming")
|
||||
self.i2c_address.storage.attr.add("no_retiming")
|
||||
self.adpll.storage.attr.add("no_retiming")
|
||||
self.adpll_stb.storage.attr.add("no_retiming")
|
||||
self.comb += [
|
||||
self.programmer.i2c_divider.eq(self.i2c_divider.storage),
|
||||
self.programmer.i2c_address.eq(self.i2c_address.storage),
|
||||
self.programmer.adpll.eq(self.adpll.storage),
|
||||
self.programmer.stb.eq(self.adpll_stb.storage),
|
||||
self.adpll_busy.status.eq(self.programmer.busy),
|
||||
self.nack.status.eq(self.programmer.nack)
|
||||
]
|
||||
|
||||
# I2C with bitbang/gateware mode select
|
||||
sda_t = TSTriple(1)
|
||||
scl_t = TSTriple(1)
|
||||
self.specials += [
|
||||
MultiReg(self.i2c_divider.storage, self.programmer.i2c_divider, "helper"),
|
||||
MultiReg(self.i2c_address.storage, self.programmer.i2c_address, "helper"),
|
||||
MultiReg(self.adpll.storage, self.programmer.adpll, "helper"),
|
||||
MultiReg(self.adpll_stb.storage, self.programmer.stb, "helper"),
|
||||
MultiReg(self.programmer.busy, self.adpll_busy.status)
|
||||
sda_t.get_tristate(pads.sda),
|
||||
scl_t.get_tristate(pads.scl)
|
||||
]
|
||||
|
||||
nack_cdc = PulseSynchronizer("helper", "sys")
|
||||
self.submodules += nack_cdc
|
||||
self.comb += nack_cdc.i.eq(self.programmer.nack)
|
||||
self.sync += [
|
||||
If(self.bitbang_enable.storage, self.nack.status.eq(0)),
|
||||
If(nack_cdc.o, self.nack.status.eq(1))
|
||||
]
|
||||
|
||||
self.bitbang_enable.storage.attr.add("no_retiming")
|
||||
self.gpio_out.storage.attr.add("no_retiming")
|
||||
self.gpio_oe.storage.attr.add("no_retiming")
|
||||
|
||||
# SCL GPIO and mux
|
||||
ts_scl = TSTriple(1)
|
||||
self.specials += ts_scl.get_tristate(pads.scl)
|
||||
|
||||
status = Signal()
|
||||
self.comb += self.gpio_in.status[0].eq(status)
|
||||
|
||||
self.specials += MultiReg(ts_scl.i, status)
|
||||
self.comb += [
|
||||
If(self.bitbang_enable.storage,
|
||||
ts_scl.o.eq(self.gpio_out.storage[0]),
|
||||
ts_scl.oe.eq(self.gpio_oe.storage[0])
|
||||
).Else(
|
||||
ts_scl.o.eq(0),
|
||||
ts_scl.oe.eq(~self.programmer.scl)
|
||||
sda_t.oe.eq(self.sda_oe.storage),
|
||||
sda_t.o.eq(self.sda_out.storage),
|
||||
self.sda_in.status.eq(sda_t.i),
|
||||
scl_t.oe.eq(self.scl_oe.storage),
|
||||
scl_t.o.eq(self.scl_out.storage)
|
||||
).Else(
|
||||
sda_t.oe.eq(~self.programmer.sda_o),
|
||||
sda_t.o.eq(0),
|
||||
self.programmer.sda_i.eq(sda_t.i),
|
||||
scl_t.oe.eq(~self.programmer.scl),
|
||||
scl_t.o.eq(0),
|
||||
)
|
||||
]
|
||||
|
||||
# SDA GPIO and mux
|
||||
ts_sda = TSTriple(1)
|
||||
self.specials += ts_sda.get_tristate(pads.sda)
|
||||
|
||||
status = Signal()
|
||||
self.comb += self.gpio_in.status[1].eq(status)
|
||||
|
||||
self.specials += MultiReg(ts_sda.i, status)
|
||||
self.comb += [
|
||||
If(self.bitbang_enable.storage,
|
||||
ts_sda.o.eq(self.gpio_out.storage[1]),
|
||||
ts_sda.oe.eq(self.gpio_oe.storage[1])
|
||||
).Else(
|
||||
ts_sda.o.eq(0),
|
||||
ts_sda.oe.eq(~self.programmer.sda_o)
|
||||
)
|
||||
]
|
||||
self.specials += MultiReg(ts_sda.i, self.programmer.sda_i, "helper")
|
||||
]
|
|
@ -24,7 +24,6 @@ class FrequencyCounter(Module, AutoCSR):
|
|||
sync_domain += divider.eq(divider + 1)
|
||||
|
||||
divided = Signal()
|
||||
divided.attr.add("no_retiming")
|
||||
sync_domain += divided.eq(divider[-1])
|
||||
divided_sys = Signal()
|
||||
self.specials += MultiReg(divided, divided_sys)
|
||||
|
@ -63,7 +62,6 @@ class WRPLL(Module, AutoCSR):
|
|||
|
||||
self.helper_reset = CSRStorage(reset=1)
|
||||
self.clock_domains.cd_helper = ClockDomain()
|
||||
self.helper_reset.storage.attr.add("no_retiming")
|
||||
self.specials += [
|
||||
Instance("IBUFGDS",
|
||||
i_I=helper_dcxo_pads.p, i_IB=helper_dcxo_pads.n,
|
||||
|
@ -110,7 +108,7 @@ class WRPLL(Module, AutoCSR):
|
|||
)
|
||||
]
|
||||
|
||||
# PL-PS shared peripheral interrupt (SPI)
|
||||
# PL->PS interrupt
|
||||
|
||||
self.submodules.gtx_tag_ev = EventManager()
|
||||
self.gtx_tag_ev.stb = EventSourcePulse()
|
||||
|
@ -124,3 +122,5 @@ class WRPLL(Module, AutoCSR):
|
|||
self.gtx_tag_ev.stb.trigger.eq(gtx_tag_stb_sys),
|
||||
self.main_tag_ev.stb.trigger.eq(main_tag_stb_sys)
|
||||
]
|
||||
|
||||
self.submodules.ev = SharedIRQ(self.gtx_tag_ev, self.main_tag_ev)
|
|
@ -22,72 +22,49 @@ mod i2c {
|
|||
fn half_period(timer: &mut GlobalTimer) {
|
||||
timer.delay_us(1)
|
||||
}
|
||||
const SDA_MASK: u8 = 2;
|
||||
const SCL_MASK: u8 = 1;
|
||||
|
||||
fn sda_i(dcxo: DCXO) -> bool {
|
||||
let reg = match dcxo {
|
||||
DCXO::Main => unsafe { csr::main_dcxo::gpio_in_read() },
|
||||
match dcxo {
|
||||
DCXO::Main => unsafe { csr::main_dcxo::sda_in_read() != 0 },
|
||||
#[cfg(has_wrpll)]
|
||||
DCXO::Helper => unsafe { csr::helper_dcxo::gpio_in_read() },
|
||||
};
|
||||
reg & SDA_MASK != 0
|
||||
DCXO::Helper => unsafe { csr::helper_dcxo::sda_in_read() != 0 },
|
||||
}
|
||||
}
|
||||
|
||||
fn sda_oe(dcxo: DCXO, oe: bool) {
|
||||
let reg = match dcxo {
|
||||
DCXO::Main => unsafe { csr::main_dcxo::gpio_oe_read() },
|
||||
#[cfg(has_wrpll)]
|
||||
DCXO::Helper => unsafe { csr::helper_dcxo::gpio_oe_read() },
|
||||
};
|
||||
let reg = if oe { reg | SDA_MASK } else { reg & !SDA_MASK };
|
||||
let val = if oe { 1 } else { 0 };
|
||||
match dcxo {
|
||||
DCXO::Main => unsafe { csr::main_dcxo::gpio_oe_write(reg) },
|
||||
DCXO::Main => unsafe { csr::main_dcxo::sda_oe_write(val) },
|
||||
#[cfg(has_wrpll)]
|
||||
DCXO::Helper => unsafe { csr::helper_dcxo::gpio_oe_write(reg) },
|
||||
}
|
||||
DCXO::Helper => unsafe { csr::helper_dcxo::sda_oe_write(val) },
|
||||
};
|
||||
}
|
||||
|
||||
fn sda_o(dcxo: DCXO, o: bool) {
|
||||
let reg = match dcxo {
|
||||
DCXO::Main => unsafe { csr::main_dcxo::gpio_out_read() },
|
||||
#[cfg(has_wrpll)]
|
||||
DCXO::Helper => unsafe { csr::helper_dcxo::gpio_out_read() },
|
||||
};
|
||||
let reg = if o { reg | SDA_MASK } else { reg & !SDA_MASK };
|
||||
let val = if o { 1 } else { 0 };
|
||||
match dcxo {
|
||||
DCXO::Main => unsafe { csr::main_dcxo::gpio_out_write(reg) },
|
||||
DCXO::Main => unsafe { csr::main_dcxo::sda_out_write(val) },
|
||||
#[cfg(has_wrpll)]
|
||||
DCXO::Helper => unsafe { csr::helper_dcxo::gpio_out_write(reg) },
|
||||
}
|
||||
DCXO::Helper => unsafe { csr::helper_dcxo::sda_out_write(val) },
|
||||
};
|
||||
}
|
||||
|
||||
fn scl_oe(dcxo: DCXO, oe: bool) {
|
||||
let reg = match dcxo {
|
||||
DCXO::Main => unsafe { csr::main_dcxo::gpio_oe_read() },
|
||||
#[cfg(has_wrpll)]
|
||||
DCXO::Helper => unsafe { csr::helper_dcxo::gpio_oe_read() },
|
||||
};
|
||||
let reg = if oe { reg | SCL_MASK } else { reg & !SCL_MASK };
|
||||
let val = if oe { 1 } else { 0 };
|
||||
match dcxo {
|
||||
DCXO::Main => unsafe { csr::main_dcxo::gpio_oe_write(reg) },
|
||||
DCXO::Main => unsafe { csr::main_dcxo::scl_oe_write(val) },
|
||||
#[cfg(has_wrpll)]
|
||||
DCXO::Helper => unsafe { csr::helper_dcxo::gpio_oe_write(reg) },
|
||||
}
|
||||
DCXO::Helper => unsafe { csr::helper_dcxo::scl_oe_write(val) },
|
||||
};
|
||||
}
|
||||
|
||||
fn scl_o(dcxo: DCXO, o: bool) {
|
||||
let reg = match dcxo {
|
||||
DCXO::Main => unsafe { csr::main_dcxo::gpio_out_read() },
|
||||
#[cfg(has_wrpll)]
|
||||
DCXO::Helper => unsafe { csr::helper_dcxo::gpio_out_read() },
|
||||
};
|
||||
let reg = if o { reg | SCL_MASK } else { reg & !SCL_MASK };
|
||||
let val = if o { 1 } else { 0 };
|
||||
match dcxo {
|
||||
DCXO::Main => unsafe { csr::main_dcxo::gpio_out_write(reg) },
|
||||
DCXO::Main => unsafe { csr::main_dcxo::scl_out_write(val) },
|
||||
#[cfg(has_wrpll)]
|
||||
DCXO::Helper => unsafe { csr::helper_dcxo::gpio_out_write(reg) },
|
||||
}
|
||||
DCXO::Helper => unsafe { csr::helper_dcxo::scl_out_write(val) },
|
||||
};
|
||||
}
|
||||
|
||||
pub fn init(dcxo: DCXO, timer: &mut GlobalTimer) -> Result<(), &'static str> {
|
||||
|
@ -288,24 +265,24 @@ pub fn main_setup(timer: &mut GlobalTimer) -> Result<(), &'static str> {
|
|||
#[cfg(has_wrpll)]
|
||||
pub mod wrpll {
|
||||
|
||||
use libboard_zynq::gic;
|
||||
use libcortex_a9::mutex::Mutex;
|
||||
|
||||
use super::*;
|
||||
|
||||
const IRQ_ID: [u8; 2] = [61, 62];
|
||||
|
||||
const TIMER_WIDTH: u32 = 24;
|
||||
const COUNTER_DIV: u32 = 2;
|
||||
|
||||
const ADPLL_MAX: i32 = (950.0 / 0.0001164) as i32;
|
||||
|
||||
const KP: i32 = 6;
|
||||
const KI: i32 = 2;
|
||||
|
||||
static BASE_ADPLL: Mutex<i32> = Mutex::new(0);
|
||||
static H_INTEGRATOR: Mutex<i32> = Mutex::new(0);
|
||||
static M_INTEGRATOR: Mutex<i32> = Mutex::new(0);
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum IRQ {
|
||||
pub enum FIQ {
|
||||
GTXTag,
|
||||
MainTag,
|
||||
}
|
||||
|
@ -313,13 +290,8 @@ pub mod wrpll {
|
|||
mod tag_collector {
|
||||
use super::*;
|
||||
|
||||
const BEATING_PERIOD: i32 = 0x4000;
|
||||
const BEATING_HALFPERIOD: i32 = 0x2000;
|
||||
|
||||
// for helper PLL
|
||||
static LAST_GTX_TAG: Mutex<u32> = Mutex::new(0);
|
||||
static FIRST_GTX_INTERRUPT: Mutex<bool> = Mutex::new(false);
|
||||
static PERIOD_DET_READY: Mutex<bool> = Mutex::new(false);
|
||||
const BEATING_PERIOD: i32 = 0x8000;
|
||||
const BEATING_HALFPERIOD: i32 = 0x4000;
|
||||
|
||||
// for main PLL
|
||||
static GTX_TAG: Mutex<u32> = Mutex::new(0);
|
||||
|
@ -328,58 +300,46 @@ pub mod wrpll {
|
|||
static MAIN_TAG_READY: Mutex<bool> = Mutex::new(false);
|
||||
|
||||
pub fn reset() {
|
||||
clear_period_det_ready();
|
||||
clear_phase_det_ready();
|
||||
*LAST_GTX_TAG.lock() = 0;
|
||||
*FIRST_GTX_INTERRUPT.lock() = true;
|
||||
clear_phase_diff_ready();
|
||||
*GTX_TAG.lock() = 0;
|
||||
*MAIN_TAG.lock() = 0;
|
||||
}
|
||||
|
||||
pub fn clear_period_det_ready() {
|
||||
*PERIOD_DET_READY.lock() = false;
|
||||
}
|
||||
|
||||
pub fn clear_phase_det_ready() {
|
||||
pub fn clear_phase_diff_ready() {
|
||||
*GTX_TAG_READY.lock() = false;
|
||||
*MAIN_TAG_READY.lock() = false;
|
||||
}
|
||||
|
||||
pub fn collect_tags(interrupt: IRQ) {
|
||||
pub fn collect_tags(interrupt: FIQ) {
|
||||
match interrupt {
|
||||
IRQ::GTXTag => {
|
||||
let mut gtx_tag_lock = GTX_TAG.lock();
|
||||
|
||||
if !(*FIRST_GTX_INTERRUPT.lock()) {
|
||||
*LAST_GTX_TAG.lock() = *gtx_tag_lock;
|
||||
}
|
||||
|
||||
*gtx_tag_lock = unsafe { csr::wrpll::gtx_tag_read() };
|
||||
*FIRST_GTX_INTERRUPT.lock() = false;
|
||||
FIQ::GTXTag => {
|
||||
*GTX_TAG.lock() = unsafe { csr::wrpll::gtx_tag_read() };
|
||||
*GTX_TAG_READY.lock() = true;
|
||||
}
|
||||
IRQ::MainTag => {
|
||||
FIQ::MainTag => {
|
||||
*MAIN_TAG.lock() = unsafe { csr::wrpll::main_tag_read() };
|
||||
*MAIN_TAG_READY.lock() = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn period_det_ready() -> bool {
|
||||
*PERIOD_DET_READY.lock()
|
||||
}
|
||||
|
||||
pub fn phase_det_ready() -> bool {
|
||||
pub fn phase_diff_ready() -> bool {
|
||||
*GTX_TAG_READY.lock() && *MAIN_TAG_READY.lock()
|
||||
}
|
||||
|
||||
pub fn get_period_error() -> i32 {
|
||||
// overflowing_sub can calculate the correct beating period when GTX_TAG roll over
|
||||
BEATING_PERIOD - ((*GTX_TAG.lock()).overflowing_sub(*LAST_GTX_TAG.lock()).0) as i32
|
||||
// n * BEATING_PERIOD - GTX_TAG(n) mod BEATING_PERIOD
|
||||
let mut period_error = (*GTX_TAG.lock()).overflowing_neg().0.rem_euclid(BEATING_PERIOD as u32) as i32;
|
||||
|
||||
// mapping tags from [0, 2π] -> [-π, π]
|
||||
if period_error > BEATING_HALFPERIOD {
|
||||
period_error -= BEATING_PERIOD
|
||||
}
|
||||
period_error
|
||||
}
|
||||
|
||||
pub fn get_phase_error() -> i32 {
|
||||
// unwrap tag difference
|
||||
// MAIN_TAG(n) - GTX_TAG(n) mod BEATING_PERIOD
|
||||
let mut phase_error = (*MAIN_TAG.lock())
|
||||
.overflowing_sub(*GTX_TAG.lock())
|
||||
.0
|
||||
|
@ -401,7 +361,7 @@ pub mod wrpll {
|
|||
}
|
||||
|
||||
#[cfg(rtio_frequency = "125.0")]
|
||||
let (h_hsdiv, h_lsdiv, h_fbdiv) = (0x058, 0, 0x0481458C94D); // 125Mhz*16383/16384
|
||||
let (h_hsdiv, h_lsdiv, h_fbdiv) = (0x058, 0, 0x04814E8F442); // 125Mhz*32767/32768
|
||||
|
||||
setup(i2c::DCXO::Helper, h_hsdiv, h_lsdiv, h_fbdiv, timer)?;
|
||||
|
||||
|
@ -416,19 +376,7 @@ pub mod wrpll {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn interrupt_setup(interrupt_controller: &mut gic::InterruptController) {
|
||||
for id in IRQ_ID.iter() {
|
||||
// setup shared peripheral interrupts (SPI)
|
||||
interrupt_controller.enable(
|
||||
gic::InterruptId(*id),
|
||||
gic::CPUCore::Core0,
|
||||
gic::InterruptSensitivity::Edge,
|
||||
0,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn set_irq(en: bool) {
|
||||
fn set_fiq(en: bool) {
|
||||
let val = if en { 1 } else { 0 };
|
||||
unsafe {
|
||||
csr::wrpll::gtx_tag_ev_enable_write(val);
|
||||
|
@ -482,6 +430,7 @@ pub mod wrpll {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
/// To get within capture range
|
||||
fn set_base_adpll(timer: &mut GlobalTimer) -> Result<(), &'static str> {
|
||||
let count2adpll =
|
||||
|error: i32| (((error) as f64 * 1e6) / (0.0001164 * (1 << (TIMER_WIDTH - COUNTER_DIV)) as f64)) as i32;
|
||||
|
@ -516,38 +465,45 @@ pub mod wrpll {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn clear_pending(interrupt: IRQ) {
|
||||
fn clear_pending(interrupt: FIQ) {
|
||||
match interrupt {
|
||||
IRQ::GTXTag => unsafe { csr::wrpll::gtx_tag_ev_pending_write(1) },
|
||||
IRQ::MainTag => unsafe { csr::wrpll::main_tag_ev_pending_write(1) },
|
||||
FIQ::GTXTag => unsafe { csr::wrpll::gtx_tag_ev_pending_write(1) },
|
||||
FIQ::MainTag => unsafe { csr::wrpll::main_tag_ev_pending_write(1) },
|
||||
};
|
||||
}
|
||||
|
||||
fn is_pending(interrupt: FIQ) -> bool {
|
||||
match interrupt {
|
||||
FIQ::GTXTag => unsafe { csr::wrpll::gtx_tag_ev_pending_read() == 1 },
|
||||
FIQ::MainTag => unsafe { csr::wrpll::main_tag_ev_pending_read() == 1 },
|
||||
}
|
||||
}
|
||||
|
||||
pub fn interrupt_handler(interrupt: IRQ) {
|
||||
tag_collector::collect_tags(interrupt);
|
||||
pub fn interrupt_handler() {
|
||||
if is_pending(FIQ::GTXTag) {
|
||||
tag_collector::collect_tags(FIQ::GTXTag);
|
||||
clear_pending(FIQ::GTXTag);
|
||||
|
||||
if tag_collector::period_det_ready() {
|
||||
helper_pll().expect("failed to run helper DCXO PLL");
|
||||
tag_collector::clear_period_det_ready();
|
||||
}
|
||||
|
||||
if tag_collector::phase_det_ready() {
|
||||
if is_pending(FIQ::MainTag) {
|
||||
tag_collector::collect_tags(FIQ::MainTag);
|
||||
clear_pending(FIQ::MainTag);
|
||||
}
|
||||
|
||||
if tag_collector::phase_diff_ready() {
|
||||
main_pll().expect("failed to run main DCXO PLL");
|
||||
tag_collector::clear_phase_det_ready();
|
||||
tag_collector::clear_phase_diff_ready();
|
||||
}
|
||||
|
||||
clear_pending(interrupt);
|
||||
}
|
||||
|
||||
pub fn helper_pll() -> Result<(), &'static str> {
|
||||
const H_KP: i32 = 2;
|
||||
const H_KI: f32 = 0.5;
|
||||
|
||||
fn helper_pll() -> Result<(), &'static str> {
|
||||
let period_err = tag_collector::get_period_error();
|
||||
let mut integrator_lock = H_INTEGRATOR.lock();
|
||||
|
||||
*integrator_lock += (period_err as f32 * H_KI) as i32;
|
||||
let mut h_adpll = *BASE_ADPLL.lock() + period_err * H_KP + *integrator_lock;
|
||||
*integrator_lock += period_err * KI;
|
||||
let mut h_adpll = *BASE_ADPLL.lock() + period_err * KP + *integrator_lock;
|
||||
|
||||
h_adpll = h_adpll.clamp(-ADPLL_MAX, ADPLL_MAX);
|
||||
set_adpll(i2c::DCXO::Helper, h_adpll)?;
|
||||
|
@ -555,15 +511,12 @@ pub mod wrpll {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn main_pll() -> Result<(), &'static str> {
|
||||
const M_KP: i32 = 12;
|
||||
const M_KI: i32 = 2;
|
||||
|
||||
fn main_pll() -> Result<(), &'static str> {
|
||||
let phase_err = tag_collector::get_phase_error();
|
||||
let mut integrator_lock = M_INTEGRATOR.lock();
|
||||
|
||||
*integrator_lock += phase_err * M_KI;
|
||||
let mut m_adpll = *BASE_ADPLL.lock() + phase_err * M_KP + *integrator_lock;
|
||||
*integrator_lock += phase_err * KI;
|
||||
let mut m_adpll = *BASE_ADPLL.lock() + phase_err * KP + *integrator_lock;
|
||||
|
||||
m_adpll = m_adpll.clamp(-ADPLL_MAX, ADPLL_MAX);
|
||||
set_adpll(i2c::DCXO::Main, m_adpll)?;
|
||||
|
@ -572,7 +525,7 @@ pub mod wrpll {
|
|||
}
|
||||
|
||||
pub fn select_recovered_clock(rc: bool, timer: &mut GlobalTimer) {
|
||||
set_irq(false);
|
||||
set_fiq(false);
|
||||
|
||||
if rc {
|
||||
tag_collector::reset();
|
||||
|
@ -584,9 +537,11 @@ pub mod wrpll {
|
|||
set_base_adpll(timer).expect("failed to set base adpll");
|
||||
|
||||
// clear gateware pending flag
|
||||
clear_pending(IRQ::GTXTag);
|
||||
clear_pending(IRQ::MainTag);
|
||||
set_irq(true);
|
||||
clear_pending(FIQ::GTXTag);
|
||||
clear_pending(FIQ::MainTag);
|
||||
|
||||
// use nFIQ to avoid IRQ being disabled by mutex lock and mess up PLL
|
||||
set_fiq(true);
|
||||
info!("WRPLL interrupt enabled");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
#[cfg(has_wrpll)]
|
||||
use libboard_artiq::si549;
|
||||
use libboard_zynq::{println, stdio};
|
||||
use libcortex_a9::{interrupt_handler, regs::MPIDR};
|
||||
use libregister::RegisterR;
|
||||
|
||||
interrupt_handler!(FIQ, fiq, __irq_stack0_start, __irq_stack1_start, {
|
||||
match MPIDR.read().cpu_id() {
|
||||
0 => {
|
||||
// nFIQ is driven directly and bypass GIC
|
||||
#[cfg(has_wrpll)]
|
||||
si549::wrpll::interrupt_handler();
|
||||
return;
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
|
||||
stdio::drop_uart();
|
||||
println!("FIQ");
|
||||
loop {}
|
||||
});
|
|
@ -1,7 +1,5 @@
|
|||
use core::sync::atomic::{AtomicBool, Ordering};
|
||||
|
||||
#[cfg(has_wrpll)]
|
||||
use libboard_artiq::si549;
|
||||
use libboard_zynq::{gic, mpcore, println, stdio};
|
||||
use libcortex_a9::{asm, interrupt_handler, notify_spin_lock, regs::MPIDR, spin_lock_yield};
|
||||
use libregister::RegisterR;
|
||||
|
@ -14,37 +12,16 @@ extern "C" {
|
|||
static CORE1_RESTART: AtomicBool = AtomicBool::new(false);
|
||||
|
||||
interrupt_handler!(IRQ, irq, __irq_stack0_start, __irq_stack1_start, {
|
||||
let mpcore = mpcore::RegisterBlock::mpcore();
|
||||
let mut gic = gic::InterruptController::gic(mpcore);
|
||||
let id = gic.get_interrupt_id();
|
||||
// IRQ ID information at https://docs.xilinx.com/r/en-US/ug585-zynq-7000-SoC-TRM/Software-Generated-Interrupts-SGI?tocId=D777grsNOem_mnEV7glhfg
|
||||
|
||||
match MPIDR.read().cpu_id() {
|
||||
0 => match id.0 {
|
||||
61 => {
|
||||
#[cfg(has_wrpll)]
|
||||
si549::wrpll::interrupt_handler(si549::wrpll::IRQ::GTXTag);
|
||||
gic.end_interrupt(id);
|
||||
return;
|
||||
}
|
||||
62 => {
|
||||
#[cfg(has_wrpll)]
|
||||
si549::wrpll::interrupt_handler(si549::wrpll::IRQ::MainTag);
|
||||
gic.end_interrupt(id);
|
||||
return;
|
||||
}
|
||||
_ => {}
|
||||
},
|
||||
1 => {
|
||||
if id.0 == 0 {
|
||||
gic.end_interrupt(id);
|
||||
asm::exit_irq();
|
||||
asm!("b core1_restart");
|
||||
}
|
||||
if MPIDR.read().cpu_id() == 1 {
|
||||
let mpcore = mpcore::RegisterBlock::mpcore();
|
||||
let mut gic = gic::InterruptController::gic(mpcore);
|
||||
let id = gic.get_interrupt_id();
|
||||
if id.0 == 0 {
|
||||
gic.end_interrupt(id);
|
||||
asm::exit_irq();
|
||||
asm!("b core1_restart");
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
|
||||
}
|
||||
stdio::drop_uart();
|
||||
println!("IRQ");
|
||||
loop {}
|
||||
|
|
|
@ -21,6 +21,7 @@ pub use pl::csr::rtio_core;
|
|||
use void::Void;
|
||||
|
||||
pub mod eh_artiq;
|
||||
pub mod fiq;
|
||||
pub mod i2c;
|
||||
pub mod irq;
|
||||
pub mod kernel;
|
||||
|
|
|
@ -37,8 +37,6 @@ use libboard_artiq::{drtio_routing, drtioaux,
|
|||
pl::csr};
|
||||
#[cfg(feature = "target_kasli_soc")]
|
||||
use libboard_zynq::error_led::ErrorLED;
|
||||
#[cfg(has_wrpll)]
|
||||
use libboard_zynq::{gic::InterruptController, mpcore::RegisterBlock};
|
||||
use libboard_zynq::{i2c::I2c, print, println, time::Milliseconds, timer::GlobalTimer};
|
||||
use libcortex_a9::{l2c::enable_l2_cache, regs::MPIDR};
|
||||
use libregister::RegisterR;
|
||||
|
@ -741,9 +739,6 @@ pub extern "C" fn main_core0() -> i32 {
|
|||
|
||||
let mut timer = GlobalTimer::start();
|
||||
|
||||
#[cfg(has_wrpll)]
|
||||
let mut interrupt_controller = InterruptController::gic(RegisterBlock::mpcore());
|
||||
|
||||
let buffer_logger = unsafe { logger::BufferLogger::new(&mut LOG_BUFFER[..]) };
|
||||
buffer_logger.set_uart_log_level(log::LevelFilter::Info);
|
||||
buffer_logger.register();
|
||||
|
@ -805,10 +800,7 @@ pub extern "C" fn main_core0() -> i32 {
|
|||
csr::gt_drtio::txenable_write(0xffffffffu32 as _);
|
||||
}
|
||||
#[cfg(has_wrpll)]
|
||||
{
|
||||
si549::wrpll::helper_setup(&mut timer).expect("cannot initialize helper Si549");
|
||||
si549::wrpll::interrupt_setup(&mut interrupt_controller);
|
||||
}
|
||||
si549::wrpll::helper_setup(&mut timer).expect("cannot initialize helper Si549");
|
||||
|
||||
#[cfg(has_drtio_routing)]
|
||||
let mut repeaters = [repeater::Repeater::default(); csr::DRTIOREP.len()];
|
||||
|
|
Loading…
Reference in New Issue