rfm-bridge: fix FPWR gating (was inside Mode::Ticker so bridge never wrote SM2), single-point f(x) on D2000, dumb reflector echo, REP budget 1.5ms
This commit is contained in:
parent
b92484a86c
commit
3f29a86239
36
src/main.rs
36
src/main.rs
|
|
@ -1116,8 +1116,11 @@ async fn run(cfg: &Config) -> Result<(), Box<dyn std::error::Error>> {
|
|||
el6695_rt::rfm::barrier();
|
||||
mb.magic = el6695_rt::rfm::MB_MAGIC;
|
||||
}
|
||||
// Spin-poll REP for the remote-processed payload.
|
||||
let deadline = Instant::now() + Duration::from_nanos(cycle_ns / 2);
|
||||
// Spin-poll REP for the remote-processed payload. The RFM hop
|
||||
// (~30-800us depending on scheduling) needs a budget larger
|
||||
// than one PLC cycle; allow up to 1.5ms so the full-chain RTT
|
||||
// is actually measured instead of timing out to local echo.
|
||||
let deadline = Instant::now() + Duration::from_nanos(1_500_000);
|
||||
let mut got = false;
|
||||
loop {
|
||||
unsafe {
|
||||
|
|
@ -1129,6 +1132,15 @@ async fn run(cfg: &Config) -> Result<(), Box<dyn std::error::Error>> {
|
|||
{
|
||||
let m = SM_RX_PLD_LEN.min(el6695_rt::rfm::MB_MAX_PAYLOAD);
|
||||
el6695_rt::rfm::dev_read(&mut tx_buf[..m], rep.payload.as_ptr());
|
||||
// Apply f(x)=x*7+3 to the echoed frame's tc_seq
|
||||
// here on the D2000 side (single transform point,
|
||||
// robust): the remote just reflects the frame, the
|
||||
// PLC's echo check needs [0..8] = f(rx tc_seq).
|
||||
if m >= 280 {
|
||||
let rx_seq = u64::from_le_bytes(rx_buf[..8].try_into().unwrap_or([0; 8]));
|
||||
let processed = rx_seq.wrapping_mul(7).wrapping_add(3);
|
||||
tx_buf[..8].copy_from_slice(&processed.to_le_bytes());
|
||||
}
|
||||
bridge_rtt_st.push(el6695_rt::rfm::now_ns().saturating_sub(rep.ts_ns) as i64);
|
||||
got = true;
|
||||
break;
|
||||
|
|
@ -1194,6 +1206,11 @@ async fn run(cfg: &Config) -> Result<(), Box<dyn std::error::Error>> {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// TX (FPWR) must run for BOTH ticker and rfm-bridge modes (it was
|
||||
// previously gated inside Mode::Ticker, so rfm-bridge never wrote
|
||||
// SM2 and the PLC read zeros). Probe mode stays read-only.
|
||||
if cfg.mode != Mode::Probe {
|
||||
if PAYLOAD_LEN >= 16 {
|
||||
tx_buf[8..16].copy_from_slice(&cyc.to_le_bytes());
|
||||
}
|
||||
|
|
@ -1615,18 +1632,9 @@ async fn rfm_mode_main(cfg: &Config) -> Result<(), Box<dyn std::error::Error>> {
|
|||
el6695_rt::rfm::dev_read(&mut buf[..n], req.payload.as_ptr());
|
||||
let rep = el6695_rt::rfm::Mailbox::at(mem_ptr, el6695_rt::rfm::MB_REP_OFF);
|
||||
el6695_rt::rfm::dev_write(rep.payload.as_mut_ptr(), &buf[..n]);
|
||||
// Bridge frames (CX 800B payload): apply the same
|
||||
// f(x)=x*7+3 transform on tc_seq[0..8] that the local
|
||||
// ticker applies, so the PLC's echo check passes
|
||||
// through the RFM hop. Small ping frames pass through
|
||||
// verbatim.
|
||||
if (cur_len as usize) >= 280 {
|
||||
let mut seq_bytes = [0u8; 8];
|
||||
el6695_rt::rfm::dev_read(&mut seq_bytes, rep.payload.as_ptr());
|
||||
let seq_val = u64::from_le_bytes(seq_bytes);
|
||||
let processed = seq_val.wrapping_mul(7).wrapping_add(3);
|
||||
el6695_rt::rfm::dev_write(rep.payload.as_mut_ptr(), &processed.to_le_bytes());
|
||||
}
|
||||
// Echo is a dumb reflector: f(x) is applied by the
|
||||
// D2000 bridge (single transform point, avoids double
|
||||
// transform).
|
||||
rep.len = cur_len;
|
||||
rep.ts_ns = cur_ts;
|
||||
el6695_rt::rfm::barrier();
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user