Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add initial Serial Wire Debug (SWD) support #30

Merged
merged 1 commit into from
Jun 2, 2020
Merged

Add initial Serial Wire Debug (SWD) support #30

merged 1 commit into from
Jun 2, 2020

Conversation

adamgreen
Copy link
Contributor

@adamgreen adamgreen commented May 19, 2019

This initial support includes the ability to perform an IDCODE scan via
ARM's Serial Wire Debug protocol.

Tested on:

  • NXP LPC43xx Cortex-M4F/M0 board with JTAG and SWD debug support.
  • NXP LPC1769 Cortex-M3 board with JTAG and SWD debug support.
  • Nordic nRF51822 Cortex-M0 with SWD debug support only.
    • This did fail on an actual product with nRF51822 due to
      an incompatability between the 1k series resistor on JTAGulator
      external data lines and the strong pull-down that the product had
      on the SWCLK line. This halved the voltage of the clock signal.
    • It worked on a PCB of my own design with a chip from the same
      family.

Notes:

  • I used the MIT License with my new source files since that is
    consistent with other external Spin modules (PropSerial for example).
    I didn't use the Creative Commons License used by the core JTAGulator
    Spin modules as using Creative Commons for software isn't really
    recommended by the Creative Commons organization:
    https://creativecommons.org/faq/#can-i-apply-a-creative-commons-license-to-software
    I see Creative Commons licenses used for other parts of Open Source
    Hardware projects such as schematics, PCB layout, etc but not the
    source code.
  • This commit includes SWDCapture, SWDTarget, UnitTest, and TestSWD
    SPIN source files which are only used for unit testing the new
    SWDHost module. They aren't compiled into JTAGulator itself so they
    have no impact on its code size or functionality. Running the TestSWD
    code on the JTAGulator will exercise the SWDHost module. Nothing
    needs to be connected to the JTAGulator headers when running the
    tests.
  • There is currently only enough SWD support to issue a line reset,
    switch from JTAG to SWD mode, and read the IDCODE. This is enough
    to run a SWD base IDCODE scan. Additional functionality that could
    be added in the future might include:
    • Reading ROM tables.
    • Reading FLASH of ARM Cortex-M processors.
    • etc.
  • Maximum speed (default speed used for scanning) of the SWDHost module
    at this time is 385kHz.

This initial support includes the ability to perform an IDCODE scan via
ARM's Serial Wire Debug protocol.

Tested on:
* NXP LPC43xx Cortex-M4F/M0 board with JTAG and SWD debug support.
* NXP LPC1769 Cortex-M3 board with JTAG and SWD debug support.
* Nordic nRF51822 Cortex-M0 with SWD debug support only.
  * This did fail on an actual product with nRF51822 due to
    an incompatability between the 1k series resistor on JTAGulator
    external data lines and the strong pull-down that the product had
    on the SWCLK line. This halved the voltage of the clock signal.
  * It worked on a PCB of my own design with a chip from the same
    family.

Notes:
* I used the MIT License with my new source files since that is
  consistent with other external Spin modules (PropSerial for example).
  I didn't use the Creative Commons License used by the core JTAGulator
  Spin modules as using Creative Commons isn't really recommended by
  the Creative Commons organization:
  https://creativecommons.org/faq/#can-i-apply-a-creative-commons-license-to-software
  I see Creative Commons licenses used for other parts of Open Source
  Hardware projects such as schematics, PCB layout, etc but not the
  source code.
* This commit includes SWDCapture, SWDTarget, UnitTest, and TestSWD
  SPIN source files which are only used for unit testing the new
  SWDHost module. They aren't compiled into JTAGulator itself so they
  have no impact on its code size or functionality. Running the TestSWD
  code on the JTAGulator will exercise the SWDHost module. Nothing
  needs to be connected to the JTAGulator headers when running the
  tests.
* There is currently only enough SWD support to issue a line reset,
  switch from JTAG to SWD mode, and read the IDCODE. This is enough
  to run a SWD base IDCODE scan. Additional functionality that could
  be added in the future might include:
  * Reading ROM tables.
  * Reading FLASH of ARM Cortex-M processors.
  * etc.
* Maximum speed (default speed used for scanning) of the SWDHost module
  at this time is 385kHz.
@joegrand
Copy link
Member

joegrand commented May 24, 2019 via email

@adamgreen
Copy link
Contributor Author

Awesome! SWD support has been a much needed feature addition, so thanks for your contribution.

You're welcome. It was definitely an itch that I needed scratched :)

I'll aim to incorporate this into the core JTAGulator code as soon as I'm able.

I think I have incorporated it into JTAGulator.spin properly but if there is anything you find that I need to change during your code review and/or testing, then let me know. I will make the necessary changes and update this PR.

@adamgreen adamgreen closed this Aug 19, 2019
@joegrand
Copy link
Member

Hey @adamgreen- Was this closed due to a technical issue or because my lack of response in doing something with it? I'm planning to incorporate this into the jtagulator-dev branch (https://github.com/grandideastudio/jtagulator-dev) for testing/verification before I turn it into actual commands for the main branch. I'd like to keep the PR open until then, but feel free to re-close if you're planning to make any changes.

@joegrand joegrand reopened this Aug 20, 2019
@adamgreen
Copy link
Contributor Author

@joegrand I still had the equipment for testing this PR sitting on my desk until recently. I figured that you weren't interested in taking the change so I packed up most of that equipment a few weeks ago. Sorry!

Feel free to reopen it and merge when you get a chance. Just realize it will take me awhile to get back up to speed on Spin and PASM before I can answer any questions and/or perform any change requests that you might have :)

@joegrand
Copy link
Member

Sounds great! I don't know when I'll get a chance to do it, but it's on the list and I'll reach out with any issues!

@whoot
Copy link

whoot commented Sep 30, 2019

+1 really looking forward for this feature

@ikarus23
Copy link

+1 looking forward to this as well. This would greatly improve the usability of the device!

@joegrand
Copy link
Member

I have a few target devices with SWD on my bench right now. Since I'm planning to do a quick fix for #34, maybe I can finally dig into this while everything is set up.

@adamgreen
Copy link
Contributor Author

Was any progress made on this? Is there something wrong with my approach that makes it too difficult to review? Maybe we should just close this PR and take a different approach?

@joegrand
Copy link
Member

It's not you, it's me ;) I have it set up on my local repo to test, but haven't done it yet. At quick glance, it looks fine and I'm not anticipating any problems. I'll report back as soon as I can!

@joegrand
Copy link
Member

Hi @adamgreen. It took me a year, but I finally tested your PR today and have time to help debug and get this integrated. Thanks for your patience :)

All of the code looks visually great and well documented. I'm able to see clock and data on my scope during an IDCODE scan. However, I've tried three target boards today with known SWD pinouts without success:

  1. nRF51822 module on a Waveshare BLE400 carrier. The yellow connector next to the module has the pins directly from the chip. SWCLK has a 12K pulldown on the module, SWDIO has nothing (schematic here: https://www.waveshare.com/w/upload/5/57/Core51822-Schematic.pdf). I also tried connecting from the actual SWD header (which just brings the same pins from the yellow connector). I've used this board via SWD with OpenOCD just fine. This one is surprising since you tested with the same type of chip. Maybe I'm doing something completely stupid with my own tool ;)

IMG_9235

  1. STMicroelectronics Nucleo STM32F103 board. The required pins go from the MCU directly to CN7, which is where I connected SWCLK, SWDIO, and GND. There's an integrated ST-Link debugger on this board, which I tried in connected and disconnected modes. I've used this board via SWD on the CN7 pins with OpenOCD just fine.

IMG_9236

  1. Olimex LPC-P1343 board. I connected directly to the SWCLK, SWDIO, and GND of the SWD connector. SWDIO has a 10k pullup, SWCLK has a 10k pulldown (schematic here: https://www.olimex.com/Products/ARM/NXP/LPC-P1343/resources/LPC-P1343-schematic.pdf). I don't think those would cause a significant enough voltage divider to affect signals going to the JTAGulator. I haven't checked that.

IMG_9238

I also tried varying the clock speeds (ranging from 1kHz to the maximum 385kHz) on the different targets with no success.

SWD> h

SWD Commands:
I   Identify SWD pinout (IDCODE Scan)
C   Set SWD clock frequency
General Commands:
V   Set target I/O voltage (1.2V to 3.3V)
H   Display available commands
M   Return to main menu
SWD> c

Current SWD clock frequency (Hz): 385000
Enter new SWD clock frequency:

Value out of range!
SWD> i

Enter starting channel [0]:

Enter ending channel [0]: 3

Possible permutations: 12
Bring channels LOW between each permutation? [y/N]:

Press spacebar to begin (any other key to abort)...
JTAGulating! Press any key to abort...

No target device(s) found!
IDCODE scan complete.
SWD>

When I first ran TestSWD (before trying target boards), all 21 tests passed. Re-running it again after testing the targets gave me the following:

.......
FAIL: inLineResetState clears on first low SWDIO detected
      target.clockCounts
        actual: 52($00000034)
      expected: 50($00000032)

FAIL: inLineResetState clears on first low SWDIO detected
      target.clockCounts
        actual: 53($00000035)
      expected: 51($00000033)
x.............

 Tests passed: 20
 Tests failed: 1
Tests ignored: 0
  Total tests: 21

After removing my female/female cables, it now passes all 21 tests again. Replacing the cables and it still passes.

I don't know if that gives you any clue about possible failures. I have multiple JTAGulator hardware here and can test those tomorrow if needed.

@joegrand
Copy link
Member

Tried another off-the-shelf unit with no success. Then, I used a board that I had modified with 270 ohm series resistors for R11-R13 to do testing for issue #3 and had success with the nRF51822 board:

SWD> i

Enter starting channel [0]:

Enter ending channel [23]:

Possible permutations: 552
Bring channels LOW between each permutation? [y/N]:

Press spacebar to begin (any other key to abort)...
JTAGulating! Press any key to abort...
------------------
SWCLK: 23
SWDIO: 22
Device ID #0: 0000 1011101100010001 01000111011 1 (0x0BB11477)


IDCODE scan complete.
SWD>

However, that board still didn't work with the Olimex LPC-P1343 or Nucleo STM32F103.

It's hard to know if the issues are solely with the hardware front-end (causing too much of a voltage divider, etc.) or if they are with the SWD implementation or both. Are you using a stock JTAGulator from Parallax?

In the meantime, I'll dig through my lab to see if I can find any more SWD-capable devices.

@adamgreen
Copy link
Contributor Author

@joegrand Thanks for testing. Sorry to see that you hit so many issues. Hopefully we can get them sorted. Unfortunately, I have forgotten almost everything about Parallax Propeller programming that I learned for this project so it might take awhile for things to come back to me :)

When I first ran TestSWD (before trying target boards), all 21 tests passed. Re-running it again after testing the targets gave me the following:

Maybe there is something non-deterministic in the unit tests that causes them to fail. I checked my notes and didn't see any remarks about that but maybe I just never hit it. Of all the issues that you are hitting, they are probably the lowest priority.

Then, I used a board that I had modified with 270 ohm series resistors for R11-R13 to do testing for issue #3 and had success with the nRF51822 board:

Good to hear that you got it to at least work with the nRF51 board as I had seen it work on one of those as well.

Are you using a stock JTAGulator from Parallax?

Yes.

Could you send me your binary so that I could test the exact same code on my device? I will dig out some hardware to rerun my tests with your binaries and mine to make sure that I get the same results. I also have acquired at least one new development board in the last year that I can try testing on as well.

Have you tried scoping the pins while running the scan to verify that you are getting good voltage swings on the signals? I would definitely check the signals at the target device end as I had seen the JTAGulator fail to raise the SWCLK signal above 1.8V on one board.

@joegrand joegrand merged commit 77f212e into grandideastudio:master Jun 2, 2020
@joegrand
Copy link
Member

joegrand commented Jun 2, 2020

@adamgreen I just pushed the latest code + your merge into the repo. This way we (and anyone else who's following this) can be on the same page for testing. I made a few modifications to your branch before merging it in mostly for consistency purposes. See the commit log.

Sorry about having to re-learn Spin. That's one of the reasons I'm lagging on maintaining the JTAGulator code base, since I have to do the same thing :)

I found another board in my lab that has an STM32F103 with SWCLK and SWDIO tied directly to the part. I'll also verify signals on the other target boards with the scope to see what they look like. I'll report back soon!

@joegrand
Copy link
Member

joegrand commented Jun 2, 2020

With the new STM32F103 board on a stock JTAGulator, I was able to successfully detect it twice in a row on the first two tries. Then, I switched to different channels and tried again with no success. I switched it back to the original configuration and still no success! Neither a reboot of the target, reduction in clock speed, or the other JTAGulator with 270 ohm resistors gives me a successful identification anymore. Quite strange.

SWD> i

Enter starting channel [0]:

Enter ending channel [3]:

Possible permutations: 12
Bring channels LOW between each permutation? [y/N]:

Press spacebar to begin (any other key to abort)...
JTAGulating! Press any key to abort...

SWCLK: 2
SWDIO: 0
Device ID #0: 0001 1011101000000001 01000111011 1 (0x1BA01477)


IDCODE scan complete.
SWD> i

Enter starting channel [0]:

Enter ending channel [3]: 13

Possible permutations: 182
Bring channels LOW between each permutation? [y/N]:

Press spacebar to begin (any other key to abort)...
JTAGulating! Press any key to abort...
------
No target device(s) found!
IDCODE scan complete.
SWD>

The target pin that is actually SWDIO is swinging from GND to 3.3V. The target pin that is actually SWCLK goes up to 2.95V (with a VADJ set to 3.3V). IIRC, the ~0.4V voltage drop is caused by the internal pull-up resistor in the TXS0108E. It's still well within range.

I'll look at the other target boards next. Besides the voltage measurements, are there any particular oscilloscope screenshots that would be helpful for you to see the correct clock/data sequence being sent?

FWIW, I can also mail you any of these boards if you need more for troubleshooting.

@joegrand
Copy link
Member

joegrand commented Jun 2, 2020

I think we might be seeing two issues here. One software-related and one hardware-related?

As you suspected, two of the other target boards have reduced voltage levels on what is the target's correct SWCLK pin:

  1. nRF51822 module on a Waveshare BLE400 carrier: SWDIO = 3.28V high, 0.1V low, SWCLK = 2.3V high, 1.06V low (some signals go from 1.06V as the high to 0V as the low)

image26101

  1. Olimex LPC-P1343 board: SWDIO = 3.3V high, 0.5V low, SWCLK = 2.575V high, 1.125V low

These boards are clearly affected by the JTAGulator series resistors (R11-R13) or the TXS0108E level translators, which are used for input protection. I'm not familiar enough with SWD to know why it could cause this behavior, especially because the pull resistors on those boards are ~10k-12k (or none at all) and shouldn't affect the voltage levels so much. Perhaps there are stronger internal pull resistors on SWD-supported chips or the resistors internal to the TXS0108E are causing an issue.

On the STMicroelectronics Nucleo board (STM32F103, a different board than I tested in my previous post), it has voltage levels within range (SWDIO = 3.25V high, 0.1V low, SWCLK = 2.875V high, 0V low), but still no detection. According to the STM32 data sheet (Table 5.3.13: I/O port characteristics), anything above ~1.83V would be considered a logic level '1'.

I'll look more closely into the SWD specification and do some experiments with the JTAGulator hardware. What concerns me, even if your code is all correct, is that having SWD support on a stock JTAGulator may cause false negatives on many targets based on the hardware insufficiencies.

If you can still report back with your test results, that would be helpful!

@adamgreen
Copy link
Contributor Author

With the new STM32F103 board on a stock JTAGulator, I was able to successfully detect it twice in a row on the first two tries. Then, I switched to different channels and tried again with no success. I switched it back to the original configuration and still no success! Neither a reboot of the target, reduction in clock speed, or the other JTAGulator with 270 ohm resistors gives me a successful identification anymore. Quite strange.

Did you just try rebooting the target device or power cycling it? I wonder if maybe the DAP gets into a bad state and a reset isn't enough to recover it but a power cycle would.

FWIW, I can also mail you any of these boards if you need more for troubleshooting.

It sounds like the Nucleo board would be the most interesting one for me to order up and debug based on your results so far.

I'll look more closely into the SWD specification and do some experiments with the JTAGulator hardware. What concerns me, even if your code is all correct, is that having SWD support on a stock JTAGulator may cause false negatives on many targets based on the hardware insufficiencies.

Hopefully that isn't the case but yeah, it would make sense to not include the SWD support if that turns out to be true.

If you can still report back with your test results, that would be helpful!

I pulled out my JTAGulator hardware this afternoon and found some hardware to test it with. Later tonight I will sync up to the latest code, run some tests and get back to you.

@joegrand
Copy link
Member

joegrand commented Jun 3, 2020

With the new STM32F103 board on a stock JTAGulator, I was able to successfully detect it twice in a row on the first two tries. Then, I switched to different channels and tried again with no success. I switched it back to the original configuration and still no success! Neither a reboot of the target, reduction in clock speed, or the other JTAGulator with 270 ohm resistors gives me a successful identification anymore. Quite strange.

Did you just try rebooting the target device or power cycling it? I wonder if maybe the DAP gets into a bad state and a reset isn't enough to recover it but a power cycle would.

Yeah, I tried that a few times. I actually found another of the exact same board, but wasn't able to get that one working, either.

FWIW, I can also mail you any of these boards if you need more for troubleshooting.

It sounds like the Nucleo board would be the most interesting one for me to order up and debug based on your results so far.

They're reasonably priced in case you want your own, but happy to loan you one, too :) Manufacturer part number = NUCLEO-F103RB

I'll look more closely into the SWD specification and do some experiments with the JTAGulator hardware. What concerns me, even if your code is all correct, is that having SWD support on a stock JTAGulator may cause false negatives on many targets based on the hardware insufficiencies.

Hopefully that isn't the case but yeah, it would make sense to not include the SWD support if that turns out to be true.

If you can still report back with your test results, that would be helpful!

I pulled out my JTAGulator hardware this afternoon and found some hardware to test it with. Later tonight I will sync up to the latest code, run some tests and get back to you.

Sounds great. Thanks!

@adamgreen
Copy link
Contributor Author

I was able to get things setup again last night and retested the code on one device (a LPC1769 based board). That scan still worked. That was all I had the time to try last night.

Today, I will try a few other boards. I do have some STM32 based boards here somewhere that I can dig out and try testing with as well.

@joegrand
Copy link
Member

joegrand commented Jun 3, 2020

Could there be a difference in the reset/initialization sequence of chips that have SW-DP instead of SWJ-DP? Or, would the SW-DP ignore the JTAG-to-SWD sequence and proceed as normal?

@adamgreen
Copy link
Contributor Author

Maybe but I don't think the nRF51 devices have a SWJ-DP and I have seen it work on one of those.

@adamgreen
Copy link
Contributor Author

Doesn't the uC on the NUCLEO-F103RB which hints at an issue in my software have a SWJ-DP?

@joegrand
Copy link
Member

joegrand commented Jun 3, 2020

Yes, the STM32F103 contains an SWJ-DP. I meant more in general as to what happens with MCUs that don't have SWJ-DP. To make sure that your code implementation will still work :)

@joegrand
Copy link
Member

joegrand commented Jun 3, 2020

Yes, the STM32F103 contains an SWJ-DP. I meant more in general as to what happens with MCUs that don't have SWJ-DP. To make sure that your code implementation will still work :)

According to the ARM SWD specification (https://static.docs.arm.com/ihi0074/a/debug_interface_v6_0_architecture_specification_IHI0074A.pdf), sending the JTAG-to-SWD sequence on a SW-DP (that doesn't contain JTAG support) will be fine:

As long as the 50 cycles with SWDIOTMS HIGH sequence is sent first, the JTAG-to-SWD select sequence does not affect SW-DP, or the SWD and JTAG protocols that are used in the SWJ-DP, and any other TAP Controllers that might be connected to SWDIOTMS.

@joegrand
Copy link
Member

joegrand commented Jun 3, 2020

Two more questions:

  1. Within SWDHost.spin there are a few sections marked "UNDONE" I can't figure out the purpose of those and will they affect certain targets?

  2. According to the ARM SWD specification, 50 more clocks should be sent after the JTAG-to-SWD sequence bytes. I don't see that in the SWD_Host code (unless it's the :IdleBus label).

Screen Shot 2020-06-03 at 12 39 50 PM

Of course, neither of these will help with the hardware/level-translation issues, but I want to make sure I understand enough of your SWD implementation to support it.

@adamgreen
Copy link
Contributor Author

Yes, the STM32F103 contains an SWJ-DP. I meant more in general as to what happens with MCUs that don't have SWJ-DP. To make sure that your code implementation will still work :)

I think I implemented it that way because:

  • It seemed from my reading of the spec that it was the safest way to make it work on the most devices. Your subsequent quoting from the spec seems to indicate the same.
  • I had tested it successfully on one SWD-DP device, the nRF51822 so it appeared to be the correct interpretation of the spec.
  • If we found a device that later contradicted this assumption, I would revisit it at that time and try to come up with a solution when I had an actual device to test with.
  • I don't think the issues you have seen so far are specific to SWD-DP only devices.

I will respond to your other 2 questions later (tonight I hope). I have to reread the code and spec again before I can answer them.

@adamgreen
Copy link
Contributor Author

Good to see that the patch got at least one more board working. Thanks for testing it out and merging the PR containing it. I was modifying my code in an attempt to diagnose my Portenta issue so I wanted to at least get that change committed before I started futzing with the code on my end.

The Saleae looks like it's not decoding the IDCODE read properly, though the JTAGulator is giving the correct results

I have seen no indication in your traces or my own that the Saleae actually knows how to decode SWD properly.

That makes me wonder if there needs to be some idle state of the pins in between permutation attempts. And, if that could also be throwing off the STM32s.

The line reset performed in resetSwJtagAndReadIdCode should put the SWD-DAP into a known state according to the spec. I don't know what else other than performing a system reset (which you have the option to perform by pulling all pins low) between runs could be done.

Do you have any other STM devices over there?

I think so but I have been trying to wrap my head around the issues that I have been hitting with my STM32H747 based board first but I have pretty much hit the limit of what I can try with that one given my limited EE knowledge anyway. It doesn't appear to be a software issue but some kind of cross talk between the SWDIO and SWCLK lines. When the target attempts to drive the SWDIO line low, the SWCLK line glitches. So as soon as the STM32 device tries to start communicating, it causes the clock signal to glitch so that no reliable readout can occur. This dip in the SWCLK signal doesn't occur when the JTAGulator drives the SWDIO signal low. In the following photo of my o-scope trace, channel 2 (the top trace) is SWDIO and the one on the bottom is SWCLK.

PortentaCrossTalk

I just looked at your latest NUCLEO capture and it appears to show the same sort of glitch on the SWCLK pin if you zoom way in on what should be the ACK bits:

Screen Shot 2020-06-06 at 7 59 11 PM

@joegrand
Copy link
Member

joegrand commented Jun 7, 2020

The Saleae looks like it's not decoding the IDCODE read properly, though the JTAGulator is giving the correct results

I have seen no indication in your traces or my own that the Saleae actually knows how to decode SWD properly.

I'm going to take a capture from actual SWD hardware (not the JTAGulator) to make sure of that and have a known-good reference. Even if the Saleae decoding is not working, the signals generated by the JTAGulator should still match the data from real hardware.

Do you have any other STM devices over there?

I think so but I have been trying to wrap my head around the issues that I have been hitting with my STM32H747 based board first but I have pretty much hit the limit of what I can try with that one given my limited EE knowledge anyway. It doesn't appear to be a software issue but some kind of cross talk between the SWDIO and SWCLK lines. When the target attempts to drive the SWDIO line low, the SWCLK line glitches. So as soon as the STM32 device tries to start communicating, it causes the clock signal to glitch so that no reliable readout can occur. This dip in the SWCLK signal doesn't occur when the JTAGulator drives the SWDIO signal low. In the following photo of my o-scope trace, channel 2 (the top trace) is SWDIO and the one on the bottom is SWCLK.

I just looked at your latest NUCLEO capture and it appears to show the same sort of glitch on the SWCLK pin if you zoom way in on what should be the ACK bits:

I see that. If it was truly crosstalk, I'd expect we would have seen it on other targets and not just the STM32s. It's possible that the JTAGulator level translator's internal one-shot is too fast and causing bouncing/reflections on the line (I've seen some bouncing like that on some targets when using JTAG). I'll try to isolate the level translator to see if I can rule out it being a hardware v. firmware issue.

But, first I'm going to get a known-good SWD capture as mentioned above.

@joegrand
Copy link
Member

joegrand commented Jun 8, 2020

In SWDHost.spin, I see this defined:

    ' Number of times to pulse SWCLK with SWDIO pulled high for line reset.
    LINE_RESET_CLK_PULSES = 50

It's not used and the number of SWCLK pulses within :ResetCmd are hard-coded. Do you suggest removing the DEFINE or using it in the PASM (something like MOV BitCount, LINE_RESET_CLK_PULSES-32)?

@adamgreen
Copy link
Contributor Author

Do you suggest removing the DEFINE or using it in the PASM (something like MOV BitCount, LINE_RESET_CLK_PULSES-32)?

Good catch. Probably better to use it in the PASM. I probably did use it when the SWD code was all written in Spin but then mistakenly hardcoded it when I rewrote it in ASM so that it would be fast enough to work with nRF51 parts (they require a clock rate of 125kHz or higher to differentiate a reset from SWD idle as that chip shares nReset and SWDIO on the same pin).

I can fix it when I update the unit tests as I broke them when I made that recent change to increase reset and idle clocks.

@joegrand
Copy link
Member

The Saleae looks like it's not decoding the IDCODE read properly, though the JTAGulator is giving the correct results

I have seen no indication in your traces or my own that the Saleae actually knows how to decode SWD properly.

Here's a good capture from an STM32F103 board using OpenOCD and Bus Blaster. You can see the reset and request for IDCODE at the beginning of the transaction (and a whole bunch of other communication as OpenOCD gets set up). I think this proves that the Saleae decoder module works as expected and we should be seeing similar captures on our targets using the JTAGulator.

You can see how the SWCLK is idling low between transactions. This doesn't seem to be the case on the NUCLEO or DC27 captures. Do you see anything by comparing captures that could point to software implementation issues?

I'm going to work on bypassing the level translators later this week to rule out any bouncing/reflections from the JTAGulator's front end (to see if that helps with the SWCLK line glitches). Just received the necessary components today.

STM32F103_Known_Good.logicdata.zip

Screen Shot 2020-06-10 at 6 54 35 PM

@adamgreen
Copy link
Contributor Author

Thanks for making that capture. As you observe, the bus blaster seems to leave SWCLK in the low state as they figure out what the next bit should be where I leave it in the high state. I don't think that explains why Saleae doesn't sync up to the beginning of our IDCODE read packet in your good DC27 capture but instead they sync up in the middle of that packet. It is like they miss our start bit and instead pick a later high bit to be the start bit. I suspect that it isn't a coincidence that it syncs up 16 clocks into the packet. I bet that they don't like the fact that I allow the clock to stop running for an extended period of time before I start this packet while the Spin code calculates the bits to place in this packet request. I will perform some experiments over the next couple of days to see if that is the case.

While I was looking at the successful DC27 capture again, I noticed that it too contains SWCLK glitches in the portion where the target is controlling SWDIO. I see it on the first rising edge of SWCLK after the turnaround which is the first ack bit output by the target. The next one occurs on the next ack bit (the first falling edge of SWDIO controlled by the target and not the JTAGulator).
DC27-ClockGlitch-ZoomedOut

The following image takes a closer look at the first of the 2 glitches annotated in the above image:
DC27-ClockGlitch-ZoomedIn

So while this capture shows a SWCLK glitch like I see in the STM32 captures, the target doesn't seem to be affected by it. Maybe STM devices don't have a Schmitt trigger on SWCLK that can filter out these glitches while devices from other vendors do?

@joegrand
Copy link
Member

That glitching could be why the Saleae isn't decoding the DC27 capture properly. But, I still think the CLK should be idling low like the known good capture, since maybe that's throwing things off instead.

I'll be standing by in case you have any more code changes and then I'll run tests with the modified hardware!

@joegrand
Copy link
Member

@adamgreen I just pushed a few changes to the higher-level JTAGulator UI. Most notably added the SWD_IDCODE_Known command (D) to display the IDCODE for a given pin permutation (doing swd.resetSwJtagAndReadIdCode). This should make testing easier since you can specify the actual pins that the target is connected to.

@adamgreen
Copy link
Contributor Author

I removed the SWCLK pauses so that it never sits in either the high or low state for longer than the currently set frequency requires. It didn't really seem to have an impact on the Saleae decoding though.

I placed this update in a new branch if you want to try it out. It has the side effect of running a little bit faster and contains some code cleanup to remove most of those UNDONEs in the PASM that you asked me about before.

@joegrand joegrand mentioned this pull request Jun 13, 2020
@joegrand
Copy link
Member

@adamgreen Is there a reason you started SWDIO and SWCLK at HIGH? Is this based on what you wrote in #38? See the "glitch" I'm seeing before sending the reset pulses, which I believe is due to setup/initialization.

Screen Shot 2020-06-16 at 5 29 16 PM

In the STM32F103_Known_Good, both start off at LOW.

I'm getting a valid read/response, but still not able to decode properly with the Saleae. I still think those beginning states are confusing it. I could be wrong, but it sure would be nice to get proper decoding!

@joegrand
Copy link
Member

OK, the initial states wouldn't matter for the analyzer, since it clearly detects both Line Resets.

Looking closer at the request for Read ICDODE:

The STM32F103 Known Good has 9 SWCLK falling edges before SWDIO goes high and then back low to start sending the data...

Screen Shot 2020-06-16 at 5 53 39 PM

The JTAGulator has 8 SWCLK falling edges and the SWDIO goes high on the 9th...

Screen Shot 2020-06-16 at 5 55 18 PM

If you toggle back and forth between those screenshots, you can see the offset of SWDIO on the known good capture. In other words, maybe the Saleae needs to have a 0 clocked in on SWDIO before it decodes the subsequent data properly.

I have no idea if this would matter. The JTAGulator can still detect it fine, so maybe I shouldn't waste our time trying to get the Saleae decoding properly. But, something still feels off...

@joegrand
Copy link
Member

Two issues with the Saleae SWD analyzer. Trying to grok...

https://github.com/saleae/swd-analyzer/issues

@joegrand
Copy link
Member

Yes, this Saleae bug was preventing us from proper decoding!

I added the following to the end of :TurnAroundDone to clock once with SWDIO high and then add some extra clocks:

MOV DataOut, #1
MOV BitCount, #IDLE_PULSES
call #ClockInOut

Screen Shot 2020-06-16 at 6 28 19 PM

NUCLEO-GOOD.logicdata.zip

The decoder is still incorrectly starting the initial Line Reset earlier than it actually is, since the initialization of SWDIO and SWCLK must be confusing it. While that would be nice to somehow fix, I don't think it's worth the effort. The targets clearly don't have an issue with it.

What do you think about leaving this code in as a fix until Saleae fixes their decoder (if ever)? Can you anticipate any problems? It shouldn't affect the target and will barely affect timing. It will also make it easier for people to debug issues with their targets since the capture will display properly.

@adamgreen
Copy link
Contributor Author

@adamgreen Is there a reason you started SWDIO and SWCLK at HIGH? Is this based on what you wrote in #38? See the "glitch" I'm seeing before sending the reset pulses, which I believe is due to setup/initialization.

I start SWCLK high because the ClockInOut routine expects it to be in the high state upon the first entry. SWDIO could be in either state. I set it high too so that it won't cause nRF51* devices to reset as they share SWDIO with nReset.

Yes, this Saleae bug was preventing us from proper decoding!

I added the following to the end of :TurnAroundDone to clock once with SWDIO high and then add some extra clocks:

MOV DataOut, #1
MOV BitCount, #IDLE_PULSES
call #ClockInOut

This is awesome! You should push that change up.

@joegrand
Copy link
Member

@adamgreen Is there a reason you started SWDIO and SWCLK at HIGH? Is this based on what you wrote in #38? See the "glitch" I'm seeing before sending the reset pulses, which I believe is due to setup/initialization.

I start SWCLK high because the ClockInOut routine expects it to be in the high state upon the first entry. SWDIO could be in either state. I set it high too so that it won't cause nRF51* devices to reset as they share SWDIO with nReset.

OK, we'll keep that as-is to avoid interfering with nRF51* devices.

This is awesome! You should push that change up.

Pushed! Let me know if you see anything problematic with it.

I'll continue my testing with different targets tomorrow!

@joegrand
Copy link
Member

The current iteration of code properly detects all of my SWD-based targets! The Saleae provides proper captures, as well. This is great news and I consider the SWD code good-to-go. I'll be releasing the official firmware version 1.7 shortly. Thanks for all the help dealing with the integration (and waiting a year to do it!)

Since we were running into signal level issues with some of the targets (discussed earlier in the thread), I ran this series of tests on a Propeller Professional Development Board (essentially a JTAGulator without the front-end circuitry and target voltage generation). This limited my I/O to 3.3V, since the pins are connected directly from the Propeller to the target.

The bad news is that there are clearly interface issues between the JTAGulator hardware and many SWD-based targets, which I'm guessing is due to pull resistor incompatibility and/or the level translators. I'm going to make a note in the CHANGES about this. As comparison, I ran all tests again with a stock JTAGulator and the only successful detection was the DEFCON 27 Badge. I need to continue experimenting with component changes, which may result in a Rev. C hardware. I'm hoping the changes will be possible for people to do on their existing Rev. B hardware, as well. I think the hardware issues are the same as #3, which has been plaguing me for many years.

Test results as follows:

STM32F103 Standalone Board: SUCCESS! (Running @ 3V VCC)

SWCLK: 17
SWDIO: 18
Device ID #0: 0001 1011101000000001 01000111011 1 (0x1BA01477)

NUCLEO: SUCCESS! (Jumpers removed from the integrated ST-Link debugger)

SWCLK: 18
SWDIO: 15
Device ID #0: 0001 1011101000000001 01000111011 1 (0x1BA01477)

Olimex LPC-P1343: SUCCESS!

SWCLK: 4
SWDIO: 9
Device ID #0: 0010 1011101000000001 01000111011 1 (0x2BA01477)

nRF51822: SUCCESS! (We knew this one already when using the modified JTAGulator w/ 270 ohm resistors)

SWCLK: 9
SWDIO: 4
Device ID #0: 0000 1011101100010001 01000111011 1 (0x0BB11477)

DEFCON 27 Badge (NXP MKL27Z64VDA4): SUCCESS! (We knew this one already using the stock JTAGulator, running @ 3V VCC)

SWCLK: 7
SWDIO: 6
Device ID #0: 0000 1011110000010001 01000111011 1 (0x0BC11477)

@joegrand
Copy link
Member

@adamgreen To simplify our source code tree, I was planning to remove the SWD test files from the main JTAGulator repo. Do you see any issue with that?

@adamgreen
Copy link
Contributor Author

The current iteration of code properly detects all of my SWD-based targets! The Saleae provides proper captures, as well. This is great news and I consider the SWD code good-to-go. I'll be releasing the official firmware version 1.7 shortly. Thanks for all the help dealing with the integration (and waiting a year to do it!)

This is great news! Thanks for working with me over the last couple of weeks to whip the SWD code into shape. Much appreciated.

The bad news is that there are clearly interface issues between the JTAGulator hardware and many SWD-based targets, which I'm guessing is due to pull resistor incompatibility and/or the level translators. I'm going to make a note in the CHANGES about this.

Would it make sense to modify the main menu text for the SWD item to note this? Maybe something like:

              byte "S   SWD (Experimental - See CHANGES.markdown)", CR, LF, LF

@adamgreen To simplify our source code tree, I was planning to remove the SWD test files from the main JTAGulator repo. Do you see any issue with that?

I don't have any issue with that.

@adamgreen
Copy link
Contributor Author

I was doing some searching on the inter webs a week or so ago for information about the TI TXS0108 and SWD/JTAG when I came across this discussion on the Black Magic Probe's Gitter feed:

Piotr Esden-Tempski @esden Jun 13 2018 12:21
@hei5enbrg the main reason why we went away from the TXS is that it has really weak drive power. Due to the "magical" and "automatic" direction control it fights basically itself all the time. If you are usig a cable that is not very short has ideal quality and there are no resistors or other protection of the target circuitry it is not working well. When we figured that this is an issue some users have I designed the version with dedicated direction switchable dual supply buffers. This made the issues go away.
@hei5enbrg so if you are asking if you should use the TXS in some project of yours. Unless you control both sides of the connection all the time do NOT use it. You and your customers will be unhappy.

@joegrand
Copy link
Member

joegrand commented Jun 17, 2020

Would it make sense to modify the main menu text for the SWD item to note this? Maybe something like:

              byte "S   SWD (Experimental - See CHANGES.markdown)", CR, LF, LF

I was thinking that, but really the SWD code isn't experimental. It's functioning properly and if people have their own hardware that doesn't use the JTAGulator front-end circuity, it will work fine. Maybe I'll add a warning within the SWD I and D commands. Like:

Warning: JTAGulator HW Rev. B and earlier have compatibility issues w/ 
many SWD-based target devices. Detection results may be affected.

Edit: Done!

@joegrand
Copy link
Member

I was doing some searching on the inter webs a week or so ago for information about the TI TXS0108 and SWD/JTAG when I came across this discussion on the Black Magic Probe's Gitter feed:

Good info! The hardest part of the JTAGulator hardware is that we don't know what signals or hardware will be connected to what channels. I have a bunch of new level translators to try, but fear that any automatic direction detection could cause problems (and possibly the speed of the internal one-shots, which might be causing the glitching/reflections we saw earlier, too). I've found an I2C-based I/O expander with integrated level translation that would enable me to individually set the direction of each I/O pin. That would require a major hardware revision, though, so I'm hoping to find some other (interim?) solutions.

I'm going to revive the #3 thread soon with a little update and then go from there. I'll take a look at the new BMP hardware, too.

@adamgreen
Copy link
Contributor Author

I was thinking that, but really the SWD code isn't experimental. It's functioning properly and if people have their own hardware that doesn't use the JTAGulator front-end circuity, it will work fine. Maybe I'll add a warning within the SWD I and D commands. Like:

Warning: JTAGulator HW Rev. B and earlier have compatibility issues w/ 
many SWD-based target devices. Detection results may be affected.

I like that warning.

Good info! The hardest part of the JTAGulator hardware is that we don't know what signals or hardware will be connected to what channels. I have a bunch of new level translators to try, but fear that any automatic direction detection could cause problems (and possibly the speed of the internal one-shots, which might be causing the glitching/reflections we saw earlier, too). I've found an I2C-based I/O expander with integrated level translation that would enable me to individually set the direction of each I/O pin. That would require a major hardware revision, though, so I'm hoping to find some other (interim?) solutions.

I was wondering if there was a level shifter that had parallel bi-directional lines like the current level shifter but had a dedicated pin for each line to manually indicate the direction? Then an I2C I/O expander could be used to just set the direction pins so that you only needed to search the sources for references to DIRA and add some I2C commands to mimic those settings? Maybe that is what you meant anyway.

I'm going to revive the #3 thread soon with a little update and then go from there. I'll take a look at the new BMP hardware, too.

Cool. I guess we can consider this thread truly closed at this point and I will subscribe to that issue and track your progress there.

@joegrand
Copy link
Member

joegrand commented Jun 17, 2020

I was wondering if there was a level shifter that had parallel bi-directional lines like the current level shifter but had a dedicated pin for each line to manually indicate the direction? Then an I2C I/O expander could be used to just set the direction pins so that you only needed to search the sources for references to DIRA and add some I2C commands to mimic those settings? Maybe that is what you meant anyway.

If I have to change the hardware significantly (e.g., not just swapping in some pin-compatible components), then I'd probably go with the I2C device and let it handle both the direction and level-shifting on each pin. I have some other ideas for level-shifting (maybe require an external target voltage tied directly to the level-shifting input, to prevent the need for the V command, would allow a wider voltage range, and would remove the target voltage circuitry from the JTAGulator), but that might be too big of a shift away from the current process. Or, add a jumper like the Bus Blaster to select between internal and external target voltage.

Edit: The I2C I/O expander may not be able to handle UART input/output very well. It should be able to do synchronous communication just fine.

Cool. I guess we can consider this thread truly closed at this point and I will subscribe to that issue and track your progress there.

Yes! We can consider this thread closed. See you on the other one :)

@ikarus23
Copy link

I Just wanted to use this thread as opportunity to say thank you! Looking at this thread it's easy to see how much effort has gone into this. SWD support is a big deal. I'm really grateful!

@joegrand
Copy link
Member

@ikarus23 Thanks for the note! @adamgreen did the hard work, I just had to do some testing and integration :) I'm happy that it all works, but now need to solve the hardware problems to support more targets!

@joegrand
Copy link
Member

joegrand commented Mar 6, 2023

Finally finished the Hardware Modifications document that describes two modifications you can do to your JTAGulator HW Rev. B front end to improve target compatibility at the expense of reduced input protection and/or level translation. Related discussion can be found in #3.

I've tested the modifications with all the devices in this thread and all are good!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants