Post Go back to editing

MAX14819 EstCom wake-up retries firing way faster than the datasheet says (~2ms instead of 30ms) — stuck after a lot of testing

Thread Summary

The user encountered issues with the MAX14819 (RevID 0x0A) failing to establish communication with an ifm DTI421 sensor over SPI. The solution involved correctly setting the message checksum octet in both transmit and receive configurations, and ensuring the CQ driver was in receive mode before enabling the framer. With these fixes, communication was established, and the Direct Parameter Page was read successfully.
AI Generated Content
Category: Hardware
Product Number: MAX14819

Hey,

We've been chasing a weird one with the MAX14819 (non-A, RevID reads 0x0A) and could use a second pair of eyes from your side.

Quick setup: STM32F413 talking to the chip over SPI, 14.7456MHz crystal (confirmed running — ExtClkMis reads clear), CQ current limit maxed out. The device on the other end is an ifm DTI421 (real IO-Link 1.1, COM2/38.4kBaud) — and we know it's not the sensor's fault, because we plugged the exact same physical unit straight into an ifm AL1060 master and it established communication with no issues at all. So the device is good, and we're stuck on why our master won't talk to it.

What we're seeing: We trigger EstCom and scope the CQ line. The wake-up pulse itself looks textbook — we measured it with cursors and got 80.09µs, 81.02µs, and 80.98µs on three separate pulses, basically dead on the datasheet's 75-85µs spec. So the pulse shape/timing is clearly right.

The problem is what happens around it. The datasheet says a failed attempt should retry after 30ms, up to 3 times. What we actually see is three pulses fired back-to-back, only 1.5-2.6ms apart, and the whole thing (from writing EstCom to it clearing with ComRt=00, i.e. "no device") wraps up in about 20-30ms total, every single time. That's not even long enough to fit ONE 30ms gap, let alone the two you'd need for 3 real retry attempts — so whatever's happening internally, it's not doing the retry sequence the datasheet describes.

A few scope details if it's useful:

  • At 200µs/div we can clearly see the 3 individual pulses, each with sharp edges, and they measure ~80µs wide each (see cursor measurements above).
  • At wider timebases (1ms/div, 500µs/div) the 3 pulses show up as one tight cluster right at the start of the capture, then dead flat for the rest of a 5-10ms window.
  • We also tried the internal 5mA sink (SourceSink=0) vs. source/pull-up (SourceSink=1) config on CQCfg — with the sink config (which matches what a couple of open-source MAX14819 drivers we found use), the 3 pulses spread out a bit more (~1.6-2.6ms apart instead of tightly bunched), and each one grew a "double-dip" shape that we think is just the sink current pulling the line down during the high-Z window — but the total attempt still wraps up in the same ~20-30ms and still reports no device.

Happy to send the actual scope screenshots (PicoScope captures) if that'd help — we've got clean shots of the individual 80µs pulses with cursor measurements, the 3-pulse cluster on a 1-2ms timebase, and the wider "spread out" version after the sink-config change.

What we've already ruled out, since none of it changed the behavior at all:

  • DeviceDly (tried POR default and the datasheet's "IO-Link compliance" values)
  • CyclTmr (tried default 0x00 and a value specifically set to target 30ms per the Table 2 formula)
  • CQCfg source vs. sink (both directions, values matching working reference drivers)
  • A couple ms of settle time inserted after ChanStat.Rst before configuring the rest
  • Doing our own software-level retries with generous 50ms+ gaps between full attempts
  • Cable/reflection weirdness — not physically possible, our wiring is centimeters long, a 2ms echo would need something like 500,000 meters of cable
  • Crystal not running — nope, confirmed fine

Questions we're hoping you can help with:

  1. Is that ~30ms retry delay hard-coded in silicon, or is it actually tied to some register we're missing (CyclTmr, DeviceDly, something else)? We're seeing more like 1.5-2.6ms.
  2. Any known erratum for this RevID (0x0A, MAX14819 non-A) around EstCom timing?
  3. Is there some register write not covered in the "Establish-Communication Sequencer" section that's actually needed to get the real 3-attempt/30ms-spaced behavior?
  4. Does CQCfg's source/sink setting have any documented (or undocumented) effect on EstCom's internal timing? We saw the pulse spacing shift a bit when we changed it, which seems like it shouldn't happen per the datasheet.
  5. Any way to peek at more detailed internal EstCom state (which COM rate it's trying, which attempt number) to help us debug further?
  6. Since the same device works fine on a different, independent master — is there anything about a specific device's physical-layer behavior that could trip up the MAX14819's autonomous EstCom sequencer specifically, versus a master that drives wake-up manually in firmware?

Thanks for any pointers — happy to share our full register config, more scope captures, or a logic analyzer trace if that'd speed things up.

Thread Notes

  • This is pretty much a dump of the registers


    -- Global --
    RevID=0x0a Clock=0x01 (ExtClkMis=0 XtalEn=1) DrvrCurrLim=0xc0
    Status=0x00 Interrupt=0x00 InterruptEn=0x40
    -- Channel 0 --
    CQCtrl=0x00 (EstCom=0 WuPuls=0 CQSend=0 ComRt=0x0)
    ChanStat=0x42 (FramerEn=1 CQFault=0 UVL+=1 L+CLim=0)
    CQCfg=0x14 MsgCtrl=0x26 DeviceDly=0x22 CyclTmr=0x7b
    CQErr=0x00 RxFIFOLvl=0x00 TrigAssgn=0x00
    -- Channel 1 --
    CQCtrl=0x00 (EstCom=0 WuPuls=0 CQSend=0 ComRt=0x0)
    ChanStat=0x42 (FramerEn=1 CQFault=0 UVL+=1 L+CLim=0)
    CQCfg=0x14 MsgCtrl=0x26 DeviceDly=0x22 CyclTmr=0x7b
    CQErr=0x80 RxFIFOLvl=0x00 TrigAssgn=0x00

    The IC has an external ossiclator as descibed in the datasheet and the power switching functionality is not used. Devices are "always on".

  • Hello,

    I would be happy to help you debug this and I am looking into it now. If possible, please send your scope shots, as I believe they will be very helpful. Let me also start by asking a couple of questions:

    (1) Is your microcontroller accessing the SPI interface after the ESTCOM sequence has been activated?  If so, what is it reading/writing?

    (2) From your description, it sounds like a first wake-up pulse happens correctly, but then another happens very shortly after that, is that correct? So there is no COM3, COM2, COM1 messaging sent - just a train of wake-up pulses?

    (3) It looks like you have enabled the driver before starting the EstCom sequence (CQCfg = 0x14), could you please try disabling the driver by setting the DrvDis_ bit (CQCfg_ = 0x16) before setting the EstCom bit? The driver should be disabled before a wake-up sequence is initiated.

    (4) From your register dump, it looks like the Interrupt registers read as 0x00 - is this before the EstCom attempt or after it?  If before, what is the Interrupt register read after the EstCom sequence completes?

    Thank you,

    Shasta

  • on Sep 9, 2026 11:02 AM in reply to ShastaThomas Contains AI Generated Content
    0

    Hi Shasta,

    Thanks for digging into this — really appreciate it. 

    (1) SPI access during EstCom: Yes — my wait loop polls the chip roughly every 10ms while EstCom is active, reading both Interrupt (0x02) and CQCtrl (0x06/07) on each iteration (I also listen on the IRQ pin, but fall back to this timed poll regardless). So I am touching SPI, including a clear-on-read register (Interrupt), during the active sequence. Happy to change this if you think it could be interfering — e.g. only reading once IRQ actually fires, rather than polling on a timer in parallel.

    (2) Confirmed — that matches exactly what I'm seeing. A wake-up pulse, then what looks like a train of additional wake-up-shaped pulses (all measuring ~80µs individually, matching the datasheet's tWU spec), not differently-sized COM3/COM2/COM1 test messages.

    (3) Tried it, and it changed something real. I set CQCfg = 0x16 (DrvDis_=1) before triggering EstCom, same as you suggested. Before this change, the whole EstCom sequence (from setting the bit to it self-clearing with ComRt=00) consistently took only ~20-30ms — too fast to fit even one 30ms retry gap. After the change, that timing shifted dramatically: I'm now seeing pulses spaced roughly 225 ms apart (measured directly on scope, three pulses in a single capture). So disabling the driver first clearly does affect the chip's internal retry timing — it's just landed on a much longer interval than the documented ~30-50ms T_DWU, rather than matching it. Does ~225ms mean anything specific on your end? It doesn't line up with anything I've found in the datasheet myself (closest is T_DSIO, 60-300ms, but that's described as device-side SIO fallback timing, not master retry spacing).

    (4) Clarified with better timing: the 0x00 in my earlier dump was read well after EstCom had already completed and after my own polling loop had already read (and cleared) it. I've since added logging that captures Interrupt at the exact moment EstCom self-clears, before anything else touches it: Interrupt = 0x40, i.e. just WURQInt set, no TxError/RxError/StatusInt alongside it. So a clean completion signal, just for a failed attempt.

    Still no device response in the end, but the driver-disable change clearly touched something real in the chip's timing behavior, which feels like a meaningful step forward. Let me know if the ~225ms number rings a bell, or if there's another register/sequencing detail worth checking next.

    Thanks again,
    Søren

  • Hey! Following up on your suggestions — thanks again, this has been a big help.

    1. DrvDis_ before EstCom/WuPuls_: I tried disabling the CQ driver before triggering EstCom, per your suggestion. It does change things, but not quite the way I first assumed. Zooming in on the wake-up pulse itself with DrvDis_ set, it's not the expected ~80µs pulse — the high level is held for about 2.1ms instead (measured 2.104ms on the scope, channel B referenced to L-, ~22-24V amplitude). The interesting part is the edges themselves are still fast and clean — I zoomed into just the rising edge at 20µs/div and it's a sharp transition, maybe 5-10µs, nothing slow or RC-limited. Right after the pulse falls, there's a burst of fast activity (possibly the COM test message from Figure 31?) before things go quiet again.

    So it looks like it's not a drive-strength/slew-rate issue — the chip is still switching the line hard and fast in both directions. It's specifically the duration the high level is held that's off, by roughly 26x (2.1ms vs the spec's 80µs). My guess is DrvDis_ is interfering with whatever internal mechanism normally times the pulse width — maybe something that senses drive current to know when to end it, which wouldn't fire correctly with the driver disabled — so it just holds until some other timeout kicks in instead.

    2. CQ polarity (InvCQ_): Separately, I put a scope probe across the CQ line (referenced to L-) on both our board and a known-good setup — a different master (an ifm AL1060) talking to a second, physically identical DTI421. The AL1060 link idles low and pulses high; ours idles high and pulses low, consistently, even with matched grounds, so it's not a probe artifact. I tried flipping InvCQ_ in MsgCtrl_ to match. It did flip the polarity on the scope like expected, but got no response from the device, and it interacted badly with the DrvDis_ change above (reverted it). I've reverted InvCQ_ and I'm running with DrvDis_ alone as the current baseline.

    3. Where I'm at: With DrvDis_ set, every attempt still ends in "no device detected." Interrupt_ reads 0x40 (WURQInt only) every time at completion — clean, no CQFault_/L+CLim_/error bits anywhere. ChanStat_ shows FramerEn=1 and UVL+=1 consistently, but that's expected on our board since L+ isn't wired (confirmed from our schematic). Full register dump attached above for reference.

    Given a 2.1ms pulse is way outside spec regardless of edge quality, I think that probably explains why comm still never establishes even with DrvDis_ set. Does the 2.1ms hold time match anything you'd expect from the internal WuPuls_/EstCom state machine when DrvDis_ is set? Trying to figure out if there's a way to get a correct ~80µs pulse width without needing DrvDis_ at all, or a different register combo that gets both right — and whether there's anything on the analog side (e.g. does L+ need to actually be driven for WURQ to register as valid on the device side) that could explain the DTI421 not responding at all, separate from the pulse width question.

    -- Global --
    RevID=0x0a Clock=0x01 (ExtClkMis=0 XtalEn=1) DrvrCurrLim=0xc0
    Status=0x00 Interrupt=0x00 InterruptEn=0x40
    -- Channel 0 --
    CQCtrl=0x00 (EstCom=0 WuPuls=0 CQSend=0 ComRt=0x0)
    ChanStat=0x42 (FramerEn=1 CQFault=0 UVL+=1 L+CLim=0)
    CQCfg=0x16 MsgCtrl=0x26 DeviceDly=0x22 CyclTmr=0x00
    CQErr=0x00 RxFIFOLvl=0x00 TrigAssgn=0x00
    -- Channel 1 --
    CQCtrl=0x00 (EstCom=0 WuPuls=0 CQSend=0 ComRt=0x0)
    ChanStat=0x42 (FramerEn=1 CQFault=0 UVL+=1 L+CLim=0)
    CQCfg=0x16 MsgCtrl=0x26 DeviceDly=0x22 CyclTmr=0x00
    CQErr=0x00 RxFIFOLvl=0x00 TrigAssgn=0x00

  • 4. Update — found the DrvDis_/pulse-width fix, and re-tested polarity cleanly:

    I pulled up two independent open-source MAX14819 driver implementations (rtlabs-com/i-link and openiolink/io-link-master-shield-hat-sw) for reference. Neither sets DrvDis_ before entering IO-Link mode — both just use push-pull + an internal current sink, driver left enabled throughout. I reverted DrvDis_ to match, and re-measured the pulse on the scope: clean ~81.5µs high period, sharp edges, right on spec. So that answers my question from point 1 — DrvDis_ isn't needed at all, and shouldn't be set.

    With that corrected baseline, I re-tested InvCQ_ — this time in isolation, without the DrvDis_ pulse-width bug confounding it like before. Confirmed on the scope: polarity now genuinely flips to idle-low/pulse-high, matching the AL1060 reference, with the ~80µs width preserved. Still zero response from the device.

    So at this point I've cleanly tested all four combinations (correct/broken pulse width × normal/inverted polarity) and gotten identical "no device detected" results every time. Current baseline is DrvDis_ reverted, InvCQ_ off, matching both reference drivers closely (CQCfg=0x14, MsgCtrl=0x26).

  • Hi Soren,

    Thank you for looking into this so thoroughly.

    My apologies for my sloppy wording previously. The datasheet notes that the CQ driver should be in receive mode (TXEN = low or TxEn = 0) before initiating a wake-up pulse, not that the driver should be disabled. I clearly used the wrong words.

    I just wanted to double check a few things regarding your latest feedback:

    (1) You noted that L+ is not wired in your circuit. Is the device getting power from somewhere else? If so, is it powered well before you trigger the EstCom sequence, or close to starting it?

    (2) Getting back to your original setup - you described in your first email that a wake-up pulse is generated correctly, but then is generated again about 2ms later, and then again, and then the establish com sequence is failed. I assume that you are still seeing that behavior now? Would it be possible to get a scope shot of the CQ line after you set the EstCom bit?

    (3) If you generate just a single wake-up pulse (WuPulseEnA = 1), what happens on the CQ line?  If you can get a scope shot, that might be helpful. 

    Thank you,

    Shasta

  • Hi Shasta,

    Thanks for the correction — that makes a lot of sense, and explains why DrvDis_ didn't get me anywhere (I'd misread your first message and disabled the whole driver, which as it turns out actually broke the wake-up pulse's timing rather than helping). I found the actual TxEn_ bit you meant in IOStCfg_ (with TXTXENDis_ in Clock_ needed to give SPI authority over it, since I don't have an external TXEN pin wired) — cross-checked against two independent open-source MAX14819 drivers, both of which clear TxEn_/Tx_ right before triggering a wake-up pulse, exactly as you described. I've implemented that now and confirmed via register readback that it's taking effect (IOStCfg_ reads 0x00 as expected). Unfortunately it didn't change the outcome — still no device detected — but I wanted to implement it properly regardless since it's clearly correct per the datasheet.

    To your three questions:

    (1) L+ power: L+ isn't wired to the MAX14819's own L+ sense pin on our board (that's why ChanStat_ always shows UVL+ set — a known/expected artifact on our schematic), but the DTI421 does get its 24V from elsewhere on our board, and I measured directly at the sensor's connector to confirm a steady ~22-24V present. Reading between the lines of your question, I suspect you may be wondering whether the device could be timing out waiting for a wake-up attempt and settling into some other state if too much time passes after power-up. I tested that directly: our normal flow calls EstCom_ from a manually-triggered shell command, which could run anywhere from seconds to minutes after power-up. So I added a temporary boot-time test that triggers EstCom_ automatically right after power-on instead, and I tried it at three different delays after L+ is applied — roughly 200ms (as fast as our boot allows), 300ms, and 1000ms, bracketing and exceeding your spec's T_DSIO_ figure (60-300ms). All three gave the identical "no device detected" result, so I don't think power-on timing explains this — the device doesn't respond whether we try almost immediately or after a full second's delay.

    (2) Scope shot of CQ after EstCom_: Yes, still seeing this behavior. Attached is a fresh capture (with the TxEn_ fix applied) — three wake-up pulses, but now spaced ~5.5-6ms apart rather than the ~1-2ms I originally described (so the TxEn_ change did shift the internal retry spacing again, similar to how DrvDis_ did before — just without breaking the pulse shape this time). Each pulse still measures a clean 80.32µs (zoomed capture also attached).

    (3) Single WuPuls_ (manual, WuPulseEnA=1): Attached. I see a single clean ~80µs pulse, and then — since I'm manually triggering a test message afterward in firmware — a burst of activity a bit later that's our attempt at sending the test message. I don't think that gap is representative of anything meaningful about the chip itself though, since it's bottlenecked by our own SPI/firmware latency (~650µs+ even after some optimization) rather than anything hardware-timed.

    At this point I've also independently ruled out the cable, the connector, and the sensor itself (swapped in the exact cable+DTI421 that works fine with a different, completely generic Class A master, straight onto our board — still nothing), and confirmed via a direct comparison against that working link that our wake-up pulse's shape and even the sensor's power delivery all look correct. Genuinely running short on ideas for what's actually different about our setup — really appreciate you continuing to work through this with me.

    Thanks, Søren

  • Hi Soren,

    Thank you for this.  I just want to double check on your procedure - can you please confirm that you do these steps in the order listed below:

    1. Verify the clock (verify that ExtClkMis is 0)

    2. Configure CQ driver into receive mode (for example, TxEn_ = 0, Tx_ = 0)

    3. Enable the framer (FramerEn_ = 1)

    4. Set EstCom = 1

    Thank you,

    Shasta

  • Hi Shasta,

    Thanks for spelling out the exact order — that turned out to be a real catch. Checking our code against your four steps, I found we had steps 2 and 3 backwards: we were enabling the framer (FramerEn_=1) before putting the driver into receive mode (TxEn_=0/Tx_=0), not after. I've fixed that so the order now matches yours exactly: verify clock → TxEn_=0/Tx_=0 → FramerEn_=1 → EstCom_=1.

    Unfortunately it didn't change the outcome — still no device detected, same clean signature as always (Interrupt_ reads 0x40 at completion, no fault bits). Register dump attached below for reference, confirming the fix is actually taking effect: IOStCfg_ reads 0x80 (TxEn_=0, Tx_=0), ChanStat_ shows FramerEn_=1, CQErr_=0x00 clean on both channels.

    -- Global --
    RevID=0x0a  Clock=0x41 (ExtClkMis=0 XtalEn=1 TXTXENDis=1)  DrvrCurrLim=0xc0
    Status=0x00  Interrupt=0x00  InterruptEn=0x40
    -- Channel 0 --
    CQCtrl=0x00 (EstCom=0 WuPuls=0 CQSend=0 ComRt=0x0)
    ChanStat=0x42 (FramerEn=1 CQFault=0 UVL+=1 L+CLim=0)
    CQCfg=0x14  MsgCtrl=0x27  DeviceDly=0x22  CyclTmr=0x00
    IOStCfg=0x80 (TxEn=0 Tx=0 CQLevel=0)
    CQErr=0x00  RxFIFOLvl=0x00  TrigAssgn=0x00
    -- Channel 1 --
    CQCtrl=0x00 (EstCom=0 WuPuls=0 CQSend=0 ComRt=0x0)
    ChanStat=0x42 (FramerEn=1 CQFault=0 UVL+=1 L+CLim=0)
    CQCfg=0x14  MsgCtrl=0x27  DeviceDly=0x22  CyclTmr=0x00
    IOStCfg=0x80 (TxEn=0 Tx=0 CQLevel=0)
    CQErr=0x00  RxFIFOLvl=0x00  TrigAssgn=0x00
    

    Since I had it fresh, I also re-ran my earlier power-on-timing test (triggering EstCom_ automatically at boot instead of via our normal manual command) with the corrected ordering in place, just in case the two interacted — same result, no device detected whether EstCom_ fires almost immediately at boot or after a deliberate delay.

    At this point I've gone through: pulse width/shape, CQ polarity, retry timing, driver register config (matches two independent reference drivers), the TxEn_/DrvDis_ distinction you clarified, power-on timing, and now operation ordering — all confirmed correct or ruled out, and the device still never responds. Cable, connector, and sensor are also independently confirmed good via a direct swap test with a different master. I'm genuinely not sure what's left to check on our side at this point — is there anything else about the MAX14819's expected behavior here that might explain a device just not responding despite all of this checking out?

    Thanks again for staying with this one, really appreciate it.

    Best, Søren

  • Hi Soren,

    Thank you for being so thorough.  Hmmm ... I am perplexed. Let me spend a day or so talking to some people who might have more insight, and I will get back to you as soon as I can.

    Thank you,

    Shasta

Before You Switch


Switching languages will make ADI Explorer unavailable. Resume your session by switching back to English and reopening ADI Explorer.