ZHCAE48 June 2024 LMK5B33216
當(dāng) PTP 協(xié)議棧在冷啟動(dòng)模式 下初始化時(shí),所有硬件寄存器(網(wǎng)絡(luò)同步器和 PTP 計(jì)時(shí) (ToD) 硬件時(shí)鐘)都必須保持未初始化狀態(tài)。使用相應(yīng)的啟動(dòng)值更新 PTP 硬件時(shí)鐘寄存器后,將寫入網(wǎng)絡(luò)同步器的完整寄存器集以初始化器件。可以使用 TICS Pro 軟件,以十六進(jìn)制文件格式生成啟動(dòng)寄存器初始化值。
僅通過改變網(wǎng)絡(luò)時(shí)序 PTP 基準(zhǔn)輸入頻率,即可調(diào)節(jié)處于穩(wěn)定狀態(tài)的 PTP 硬件計(jì)時(shí)時(shí)鐘。PTP 時(shí)鐘伺服環(huán)路通過在 LMK5XXXXXS1 中對內(nèi)部 DCO 進(jìn)行編程來修改輸出頻率。syn1588? PTP 協(xié)議棧軟件的相應(yīng)示例代碼段如下所示。在下面的示例代碼中,實(shí)現(xiàn)了兩個(gè)函數(shù):getDrift 和 setDrift。getDrift 函數(shù)從網(wǎng)絡(luò)同步器讀取頻率調(diào)整的當(dāng)前值,而 setDrift 函數(shù)使用用戶提供的值更新頻率調(diào)整。
從時(shí)間戳中提取的原始輸入數(shù)據(jù)會(huì)重新進(jìn)行格式化,并使用源自 TICS Pro 軟件的比例因子調(diào)整為 ns/s。包含 PTP 事件報(bào)文的時(shí)間信息通過預(yù)濾波器傳播,并發(fā)送至相位內(nèi)插 (PI) 伺服器,由其計(jì)算新的頻率調(diào)整值。新的頻率值傳遞給函數(shù) setDrift,后者從網(wǎng)絡(luò)同步器讀取當(dāng)前頻率偏移,計(jì)算新的漂移值,相應(yīng)地重新調(diào)整漂移的大小和格式,并使用新的 DCO 調(diào)整值以及是遞增還是遞減 DCO 頻率來更新 DPLL。
static constexpr double magic_factor = 247390116249 / 100000.0;
ptp::scalednanoseconds ptp::ti::Osc::getDrift() const
{
auto values = readRegs(ptp::ti::Register::DPLL2_FB_NUM_STAT_4, 4);
std::uint64_t value = 0;
value |= values[0];
value |= static_cast<std::uint64_t>(values[1]) << 8;
value |= static_cast<std::uint64_t>(values[2]) << 16;
value |= static_cast<std::uint64_t>(values[3]) << 24;
// if MSB is 1 handle two's complement
if (value > (1ull << 39)) value = -((value ^ 0xffffffffff) + 1);
auto drift = std::chrono::duration<double>(value / magic_factor);
return std::chrono::duration_cast<ptp::scalednanoseconds>(drift);
}
void ptp::ti::Osc::setDrift(ptp::scalednanoseconds drift)
{
// Check for absolute limits
if(drift > std::chrono::microseconds(400)) drift = std::chrono::microseconds(400);
if(drift < std::chrono::microseconds(-400)) drift = std::chrono::microseconds(-400);
ptp::scalednanoseconds drift_diff = drift - getDrift();
if(drift_diff == std::chrono::seconds(0)) {return;} // nothing to do
// check for limit per change
if(drift_diff > std::chrono::nanoseconds(40000)) drift_diff = std::chrono::nanoseconds(40000);
if(drift_diff < std::chrono::nanoseconds(-40000)) drift_diff = std::chrono::nanoseconds(-40000);
auto driff_f = std::chrono::duration_cast<std::chrono::duration<double, std::nano>>(drift_diff).count();
auto value = static_cast<std::uint64_t>(magic_factor * std::abs(driff_f));
auto values = std::vector<std::uint8_t>(5, 0x00);
std::copy(reinterpret_cast<std::uint8_t *>(&value),reinterpret_cast<std::uint8_t *>(&value)+5, values.rbegin());
writeRegs(ptp::ti::Register::DPLL2_FBFDEV_BY4, values);
// if we have a positive drift, the PLL has to be slowed down 1 is decrement, 0 is increment speed
std::uint32_t direction = drift_diff.count() > 0 ? 1: 0;
writeReg(ptp::ti::Register::DPLL2_FBFDEVUPDATE, direction);
m_currentDrift = m_currentDrift + drift_diff;
}