3
\$\begingroup\$

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 (update: this is not the problem. Driving SWD on the falling edge of SWC makes sense because according to my tests, the target samples it on the rising edge. Too bad this isn't documented.)
  • 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.

Unfortunately nobody knows how to compile the complete DAPLink firmware so I ended up writing my own probe firmware in order to complete the analysis.

\$\endgroup\$
10
  • \$\begingroup\$ 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. \$\endgroup\$ Aug 27, 2023 at 1:12
  • \$\begingroup\$ @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. \$\endgroup\$ Aug 27, 2023 at 1:48
  • \$\begingroup\$ 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. \$\endgroup\$ Aug 27, 2023 at 1:54
  • \$\begingroup\$ @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. \$\endgroup\$ Aug 27, 2023 at 2:03
  • \$\begingroup\$ 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? \$\endgroup\$ Aug 27, 2023 at 2:19

3 Answers 3

1
\$\begingroup\$

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.
\$\endgroup\$
8
  • \$\begingroup\$ 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). \$\endgroup\$ Aug 27, 2023 at 2:59
  • \$\begingroup\$ 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? \$\endgroup\$ Aug 27, 2023 at 3:05
  • \$\begingroup\$ 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. \$\endgroup\$ Aug 27, 2023 at 3:06
  • \$\begingroup\$ 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"). \$\endgroup\$ Aug 27, 2023 at 3:08
  • \$\begingroup\$ Have you looked to the vendor for support? Specifically: os.mbed.com/platforms/MAX32660EVSYS/#known-limitations \$\endgroup\$ Aug 27, 2023 at 3:28
1
\$\begingroup\$

1. Crosstalk

Well, this is embarrassing...

It turns out that many of the success/failure observations were more correlated with the time of day than with which probe I was using. Well, and I was using different probes at different times of day, so I made some false correlations.

The problem seems to be that some of the programs I was putting in the target (for the purposes of testing the transfer of the program over SWD) were actually driving the line in the ribbon cable between SWD and SWC.

SWD seems to pick up 1.5 volts of noise - easily enough to disrupt communication.

enter image description here

The solution is just shielding: have GND or VDD on signals adjacent to SWD and SWC in the ribbon cable. Then all probes work fine with an 18 inch cable. (If this is too expensive, maybe reduce the drive strength of the aggressor signals instead, if that works.)

This might also explain why increasing drive strength of SWD/SWC was causing more failures: Yes, it speeds them up, but it also causes more crosstalk. Particularly, if SWC is too strong, and the target is sampling off SWC (I wish we had the specs to know how this works...) then it disrupts SWD at precisely the moment it is being sampled.

I noticed that the MAX32660 has a slewtime config on some pins. Combining this with increased drive would seem to be an ideal solution: make the signal robust, while also not interfering with other signals.

Since my current probe firmware is running at very low speeds, the economical solution might be just a tiny capacitor on the probe side. That effectively cuts the impedance and slewrate at the same time. At the cost of speed.

2. Potential power integrity issues on both ends of the cable

The following symptoms point to power supply integrity issues:

  • I was able to cause SWD resets by toggling GPIOs that are not connected to long cables. Also by simply loading the SWD and SWC lines with 1nF capacitors (and slowing the clock accordingly). Particularly the SWD line - the one driven by the target. So maybe there is marginal power quality inside the target somewhere?

  • Sometimes the target MAX32660 output is shifted by one bit, with incorrect parity accordingly, as if the target received an extra clock pulse that I don't see on the scope.

  • Target possibly reports power-on detection at unexpected times

  • Ringing observed on the power supply (maybe 500mV. Potentially there is more inside the IC?).

  • To save 99% on PCB prototypes, I opted out of the fancy 8-layer buried micro-via options. Therefore my ground plane has some cuts that are bridged with vias. (Redundant vias, but still that's some inductance)

  • My custom probe works worse when I increase SWC drive strength (due to slewrate too fast). On the other hand, adding a buffer chip to the MAX32660-EVSYS makes it work better. I now believe that this is due not to drive strength, but due to unloading the programmer MCU's local power caps.

Bottom line, if you are switching a large load, make sure the power supply can handle it. When driving a long cable, use a separate buffer IC with its own bypass cap (or two). Especially if the slewrates are really fast.

\$\endgroup\$
0
\$\begingroup\$

I asked ADI whether my setup with the MAX32660-EVSYS and longer cable should work, and received the following response:

There should be no issues with using the MAX32660EVSYS board to program a separate MAX32660. There are no reported issues with the MAX32660 and these Evaluation System boards have been used in past projects with other remote devices. It is possible that there is a connection or setup issue.

One thing to keep in mind is that the logic levels need to match the target device. Cable quality and reliable connections may also be playing a role. The microcontrollers are not meant to be connected with long cables. This requires some type of buffer to make sure the added capacitance of the cable does not affect the digital data. The cable length you are using should be okay.

It's possible that the issue is with the breakout board. Aside from the breakout board, the setup looks like it should work.

Adding the suggested clock buffer and solving cable crosstalk appears to solve the problem.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.