1

My MAX32660-EVSYS frequently fails to start pyocd and/or program the target when the ARM SWD (Single Wire Debug) cable (connecting it to the target MAX32660) is 12 inches or longer. It appears that the protocol is running really slow (<1MHz) so I would not expect such a short cable to have any issues. What might be making the protocol fail?

Circuit topology

I am using the MAX32660-EVSYS's integrated programmer to program a MAX32660 production target on a separate board. It is a straight connection via a 12-inch ribbon cable: SWD to SWD, and SWC to SWC.

Note: The MAX32660-EVSYS ships with an on-board evaluation target IC that also connects to the same SWC/SWD lines. To prevent the evaluation target from interfering with the production target, I severed the SWD line on the evaluation target IC. And SWC is input-only on the evaluation target.

So there is just a 12 inch ribbon cable connecting the EVSYS programmer to the production target. SWD to SWD, and SWC to SWC, with no other circuit elements. I run 50MHz SPI over this same ribbon cable without issues. It does not require termination because it is not a transmission line (the flight time is much shorter than any of the clock periods involved).

Zero issues if I use a 6 inch cable instead of the 12 inch cable.

No change if I use the same power supply on both boards or separate power supplies (with ground connected via the ribbon cable).

No change if I try all the pullup/pulldown resistor settings in the MAX32660 GPIO module. Actually maybe it changes presence of the drifting that I see on the scope (which is odd, as the slewtimes I see can't be explained by the pullup/pulldown resistor; they're 10X too slow). But it does not change the cable length at which the failure occurs.

enter image description here System setup. Issues described seen with 10 inches of total cable (6 inch x 25mil ribbon plus 4 inch x 50mil ribbon). IC on the breakout board is for boosting SPI. There are no components on the SWD/SWC signals, apart from the programmer and target.

Drifting Signals

On the scope, with the 12 inch cable, most bits have great transition times. Only a few of the bus turn bits have unreasonable transition times (both up and down unfortunately - so there's no simple resistor fix).

A good programmer design wouldn't ever rely on the behavior of the bus during the undriven time. Nonetheless, these unexpectedly slow transition times are prime suspects, as they appear to cause the signal to cross the logic threshold around the time of the next clock edge (which potentially samples the signal if the programmer is buggy).

enter image description here slowly falling signal (yellow=SWD, blue=SWC) when handing control from EVSYS to target. Note EVSYS is out of spec in driving data on negative clock edges.

enter image description here slowly rising signal (yellow=SWD, blue=SWC) when handing control from target back to EVSYS. Note EVSYS is out of spec in driving data on negative clock edges.

Driver Analysis

I separated the two ends of the SWD signal by a 5 kiloohm resistor so that we can tell which end is driving it. It appears that the drifting is happening during the bus turn, which makes sense as the signal is briefly floating. (I've updated the first scope picture above to label the bits accordingly). What doesn't make sense is that making the cable long enough to align the drifting to the clock period would cause a failure. Coincidence? Or is there a bug that causes one end to sample a floating signal and generate an error?

enter image description here (yellow = EVSYS SWD, blue = target SWD)

Update

I now occasionally see a similar but more minor issue with a 6 inch cable as well. The issue is only when starting pyocd. I get this:

0000568:ERROR:discovery:Exception while probing AP#0: Unexpected ACK value (0) returned by probe

Interestingly, the issue only occurs when a pullup resistor is not enabled in the GPIO. The message above seems to suggest that the first ACK bit is being read as 1 instead of 0. So perhaps the EVSYS is just reading the bus too early (getting the pullup value rather than the actual driven value).

Given that the EVSYS is driving the bus on the wrong clock phase, it's not a wild leap to conjecture that it may be sampling it on the wrong clock phase too. Maybe an extra clock inversion somewhere? However, this wouldn't explain why a longer cable doesn't work. So there may be at least 3 bugs:

  • EVSYS drives SWD on the wrong clock phase
  • EVSYS samples SWD on the wrong clock phase during pyocd startup
  • EVSYS is slow at releasing the bus (leading to unexpectedly long transition times when enabling weak pulldown)
  • EVSYS relies on the short cable length somehow during programming (could be setup time issue; see below)

A related question is whether a pullup is generally recommended. The Arm spec is vague. One would assume that the EVSYS doesn't require a pullup, since it is self-contained (with the evaluation MAX32660 on it) and doesn't have the pullup. (It is interesting that the MAX32660 doesn't have an internal pullup by default, while other vendors have it. Perhaps because the MAX32660 allows the SWD pins to be used as GPIO)

Unfortunately, I tried 3k and 10k pullup resistors, and, while they solved this minor issue with pyocd startup, they did not solve any of the issues with the 12 inch cable.

Update - setup time issue?

I noticed that actually the EVSYS is driving the data before the falling clock edge. I can't tell from the spec which edge the data is supposed to be sampled on. But if we suppose that it's sampled on the falling clock edge, then the timings look much more marginal. I collected a long waveform, and found that in a few cases the data switches less than 100ns before the falling clock edge, as shown below. That's still a long time, but short enough that a weak pullup/pulldown would not be able to switch it fast enough (8.5 kiloohms * 15pF > 100ns).

enter image description here

Furthermore, if I zoomed into a few cases and saw setup times of 200ns and 100ns, it seems likely there might be even smaller values. Given that the transition times are on the order of 100ns, the operation is really marginal. This is all assuming sampling on the falling edge...

Interestingly, the pyocd frequency setting does not change the time between data transition and falling clock edge. (also it doesn't solve the problem, even reducing all the way to 5KHz under various combinations of target pullup and drive strength settings). For example reducing the setting from 5MHz to 1MHz yields the following (note slower timescale).

enter image description here

EVSYS Firmware

The EVSYS firmware is possibly open-source, as it appears to be CMSIS-DAP, which has evolved into the github project DAPLink. It looks like the pin-wiggling code uses the following 3 macros to do everything:

#define SW_CLOCK_CYCLE()                \
  PIN_SWCLK_CLR();                      \
  PIN_DELAY();                          \
  PIN_SWCLK_SET();                      \
  PIN_DELAY()

#define SW_WRITE_BIT(bit)               \
  PIN_SWDIO_OUT(bit);                   \
  PIN_SWCLK_CLR();                      \
  PIN_DELAY();                          \
  PIN_SWCLK_SET();                      \
  PIN_DELAY()

#define SW_READ_BIT(bit)                \
  PIN_SWCLK_CLR();                      \
  PIN_DELAY();                          \
  bit = PIN_SWDIO_IN();                 \
  PIN_SWCLK_SET();                      \
  PIN_DELAY()

The only knobs I see are fast_clock (boolean) and clock_delay (used in PIN_DELAY(); reciprocal of frequency?). Unfortunately there don't seem to be knobs to try adding delays, say, between PIN_SWDIO_OUT() and PIN_SWCLK_CLR(), nor between PIN_SWDIO_IN() and PIN_SWCLK_SET(), nor between PIN_SWDIO_OUT_ENABLE() and PIN_SWDIO_OUT(), etc.

I guess I'm supposed to recompile DAPLink myself then?? Or just buy a J-Link that costs 50 times more??

MAX32625PICO

I repeated the experiments replacing the MAX32660-EVSYS with MAX32625PICO. The results are similar: works fine with short cable, but only at certain times of the day with longer cable.

Again, I tried a few different longer cables, which work perfectly well with 50MHz signals. The common element in all of these "long" cable failures is the DAPlink firmware.

personal_cloud
  • 317
  • 4
  • 11
  • Please show photos of the circuit, including the comms link. I suspect you have transmission line problems, that is: to work properly the comms link must be a "good transmission line", but what you have may be a "poor transmission line", for various reasons. – Fabio Barone Aug 27 '23 at 01:12
  • @Fabio I added a paragraph describing the topology. It doesn't need to be a transmission line because SWD is running very slowly (<1MHz)... Or perhaps by "good transmission line" you just mean balanced transitions and adequate drive strength. (For instance RS232 barely works above 1MHz because it has neither). Generally the rise and fall times look great: they're much faster than the clock period. Except during the bus turn, where I suspect a bug. – personal_cloud Aug 27 '23 at 01:48
  • Yes, all these issues contribute to what is considered a "good transmission line", & hence photos of your apparatus would help reduce the problem space of what could be causing a "poor transmission line". Then we could ask more intelligent questions and get to a solution faster. Cheers. – Fabio Barone Aug 27 '23 at 01:54
  • @Fabio That's a good idea, though the system has a lot more in it than just the SWD/SWC signals. My choices are either present the entire system and get 1,000 questions, or isolate the problem down to a simpler system with the same SWD/SWC connections. I have described the SWD/SWC connections; reducing the system to further isolation the problem will take more time. – personal_cloud Aug 27 '23 at 02:03
  • You mentioned "(which is odd, as the slewtimes I see can't be explained by the pullup/pulldown resistor; they're 10X too slow". I think this may be the key here. Is the device giving up control of the bus changing from low to high impedance too slowly? – Fabio Barone Aug 27 '23 at 02:19
  • And perhaps could you identify the STOP & PARK bits in the packet on the scope. Cheers. – Fabio Barone Aug 27 '23 at 02:24
  • @Fabio Yes of course. I've updated the first scope picture. It's interesting to note that EVSYS is driving on the negative clock edge while the target is driving on the positive clock edge. While the spec says that both should be driving on the positive clock edge. So that seems like at least 1 bug in the EVSYS. (forgive me for wanting to save 90% on the programmer cost). – personal_cloud Aug 27 '23 at 02:33
  • @Fabio Yes, the EVSYS giving up control of the bus too slowly definitely sounds like a reasonable hypothesis for how we can get the unexpected slewtimes. Good thinking. Though it's clearly giving up the bus fast enough for the target to drive it. There must also be a bug where it's sampling the bus, unnecessarily checking its state while it's turning. The target seems well-behaved so far as I can tell. In fact, I have just renamed the question to point the finger at the EVSYS. – personal_cloud Aug 27 '23 at 02:37

2 Answers2

1

I suspect the answer is two-fold:

  1. One of the devices on the bus here is not giving up control of the bus as quickly as it should, from the OP comment here:

No change if I try all the pullup/pulldown resistor settings in the MAX32660 GPIO module. Actually maybe it changes presence of the drifting that I see on the scope (which is odd, as the slewtimes I see can't be explained by the pullup/pulldown resistor; they're 10X too slow).

Possible solution: don't rely on the resistors in the GPIO module, install external pull/down resistors, start with values of x2 the expected value of the GPIO resistors. Do they have the expected effect? If "no", then perhaps the resistors in the GPIO module are not quite right somehow.

  1. The length of the cable that causes the problem is probably related to the parasitic capacitance being just the right value to cause the slow transition signal (due to problem 1 above) to be detected as a valid signal. And of course, the value of parasitic capacitance will be set by the length of the cable.
Fabio Barone
  • 556
  • 14
  • Good points. (1) As for pullup/pulldown values, I measured them; they are 8.5 kiloohms which are in spec. So a 2.5us slewtime would require a 300pF capacitor somewhere. I estimate the total signal capacitance at around 15pF. Note the issue occurs without pullup/pulldown. I tried adding external resistors of a few values but I suspect it's a two-sided problem (sometimes release from 0, sometimes from 1). – personal_cloud Aug 27 '23 at 02:59
  • RE "sometimes release from 0, sometimes from 1". Hmmm.... I thought the PARK bit was always 1, so the release should always be from 1? – Fabio Barone Aug 27 '23 at 03:05
  • Nonetheless, you must be right that the cable is affecting parasitic capacitance which affects a transition time. At these speeds, I can't think of any other possible mechanism whereby a long cable breaks something. The question is really why is the EVSYS depending on the behavior of an undriven bus. All I can think of is it just wasn't tested very thoroughly, and happened to work with everything being on one board. – personal_cloud Aug 27 '23 at 03:06
  • You're right, PARK is always 1. So I guess the second scope image is in the other direction: The last bit of the target acknowledgement is 0, and then the bus turns back to the host. In fact we can confirm this due to the clock phase bug I previously noted. I don't know where the failure actually happens (pyocd just says "probe didn't acknowledge"). – personal_cloud Aug 27 '23 at 03:08
  • Have you looked to the vendor for support? Specifically: https://os.mbed.com/platforms/MAX32660EVSYS/#known-limitations – Fabio Barone Aug 27 '23 at 03:28
  • That's a good idea. I've opened a case with ADI (formerly Maxim). – personal_cloud Aug 27 '23 at 04:07
  • Excellent - please be sure to let us know what the root cause of this problem was, and please don't forget to upvote according to the site rules. Good luck, and cheers. – Fabio Barone Aug 27 '23 at 05:51
  • Update: I think your analysis is accurate, but perhaps I found a bigger issue. I've posted some questionable-looking timings that I found by manually browsing the entire connection sequence. – personal_cloud Aug 29 '23 at 05:19
0

It appears that the protocol is running really slow (<1MHz) so I would not expect such a short cable to have any issues.

The above is not solid reasoning. It is probably running slow because there is slow firmware flipping pins. This does not imply that there is a lot of timing margin on the wire (see "setup time" update in the question). Combined with super-weak drivers which we might guess are not designed to work with a cable, timing could be violated when a cable is added.

I need to confirm with ADI whether we should expect the programmer to work with a cable.

personal_cloud
  • 317
  • 4
  • 11