forked from M-Labs/humpback-dds
urukul: failsave for PLL timeout
This commit is contained in:
parent
adc5807ff1
commit
f1069d951d
33
src/dds.rs
33
src/dds.rs
@ -253,7 +253,12 @@ where
|
|||||||
}
|
}
|
||||||
// Finally, try enabling PLL
|
// Finally, try enabling PLL
|
||||||
else {
|
else {
|
||||||
self.enable_pll(f_sys_clk)
|
self.enable_pll(f_sys_clk)?;
|
||||||
|
if self.f_sys_clk == self.get_sys_clk_frequency()? {
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
Err(Error::WaitRetry)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -844,6 +849,32 @@ where
|
|||||||
pub fn get_f_sys_clk(&mut self) -> f64 {
|
pub fn get_f_sys_clk(&mut self) -> f64 {
|
||||||
self.f_sys_clk
|
self.f_sys_clk
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Acquire real f_sys_clk
|
||||||
|
pub fn get_sys_clk_frequency(&mut self) -> Result<f64, Error<E>> {
|
||||||
|
// Calculate the new system clock frequency, examine the clock tree
|
||||||
|
let mut configuration_queries = [
|
||||||
|
// Acquire PLL status
|
||||||
|
(DDSCFRMask::PLL_ENABLE, 0),
|
||||||
|
// Acquire N-divider, to adjust VCO if necessary
|
||||||
|
(DDSCFRMask::N, 0),
|
||||||
|
// Acquire REF_CLK divider bypass
|
||||||
|
(DDSCFRMask::REFCLK_IN_DIV_BYPASS, 0)
|
||||||
|
];
|
||||||
|
|
||||||
|
self.get_configurations(&mut configuration_queries)?;
|
||||||
|
if configuration_queries[0].1 == 1 {
|
||||||
|
// Recalculate sys_clk
|
||||||
|
let divider :f64 = configuration_queries[1].1.into();
|
||||||
|
Ok(self.f_ref_clk * divider)
|
||||||
|
}
|
||||||
|
else if configuration_queries[2].1 == 0 {
|
||||||
|
Ok(self.f_ref_clk / 2.0)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Ok(self.f_ref_clk)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Strong check for bytes passed to a register
|
// Strong check for bytes passed to a register
|
||||||
|
@ -30,6 +30,16 @@ pub enum Error<E> {
|
|||||||
MqttCommandError,
|
MqttCommandError,
|
||||||
VectorOutOfSpace,
|
VectorOutOfSpace,
|
||||||
StringOutOfSpace,
|
StringOutOfSpace,
|
||||||
|
WaitRetry, // Prompt driver to just wait and retry
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<E> Error<E> {
|
||||||
|
pub fn is_wait_retry(&self) -> bool {
|
||||||
|
match self {
|
||||||
|
Error::WaitRetry => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
@ -330,16 +340,39 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_channel_sys_clk(&mut self, channel: u8, f_sys_clk: f64) -> Result<(), Error<E>> {
|
pub fn set_channel_sys_clk(&mut self, channel: u8, f_sys_clk: f64) -> Result<(), Error<E>> {
|
||||||
self.dds[usize::from(channel)].set_sys_clk_frequency(f_sys_clk).map(|_| ())
|
loop {
|
||||||
|
if let Err(e) = self.dds[usize::from(channel)].set_sys_clk_frequency(f_sys_clk).map(|_| ()) {
|
||||||
|
if e.is_wait_retry() {
|
||||||
|
cortex_m::asm::delay(400_000);
|
||||||
|
} else {
|
||||||
|
return Err(e);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_channel_sys_clk(&mut self, channel: u8) -> Result<f64, Error<E>> {
|
pub fn get_channel_sys_clk(&mut self, channel: u8) -> Result<f64, Error<E>> {
|
||||||
Ok(self.dds[usize::from(channel)].get_f_sys_clk())
|
Ok(self.dds[usize::from(channel)].get_f_sys_clk())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_channel_calculated_sys_clk(&mut self, channel: u8) -> Result<f64, Error<E>> {
|
||||||
|
self.dds[usize::from(channel)].get_sys_clk_frequency()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn borrow_dds(&mut self, channel: u8) -> &mut DDS<SPI> {
|
||||||
|
&mut self.dds[usize::from(channel)]
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn borrow_config_register(&mut self) -> &mut ConfigRegister<SPI> {
|
||||||
|
&mut self.config_register
|
||||||
|
}
|
||||||
|
|
||||||
// Multi-dds channel functions
|
// Multi-dds channel functions
|
||||||
// Do not allow reading of DDS registers
|
// Do not allow reading of DDS registers
|
||||||
// Make sure only 1 SPI transaction is compelted per function call
|
// Make sure only 1 SPI transaction is completed per function call
|
||||||
|
|
||||||
// Setup NU_MASK in configuration register
|
// Setup NU_MASK in configuration register
|
||||||
// This selects the DDS channels that will be covered by multi_channel DDS (spi3)
|
// This selects the DDS channels that will be covered by multi_channel DDS (spi3)
|
||||||
|
Loading…
Reference in New Issue
Block a user