-
Notifications
You must be signed in to change notification settings - Fork 91
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
Conversation
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.
Awesome! SWD support has been a much needed feature addition, so thanks for your contribution. I'll aim to incorporate this into the core JTAGulator code as soon as I'm able.
|
You're welcome. It was definitely an itch that I needed scratched :)
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. |
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 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 :) |
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! |
+1 really looking forward for this feature |
+1 looking forward to this as well. This would greatly improve the usability of the device! |
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. |
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? |
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! |
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:
I also tried varying the clock speeds (ranging from 1kHz to the maximum 385kHz) on the different targets with no success.
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:
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. |
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:
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. |
@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 :)
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.
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.
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. |
@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! |
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.
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. |
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:
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! |
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.
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.
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.
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. |
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.
They're reasonably priced in case you want your own, but happy to loan you one, too :) Manufacturer part number = NUCLEO-F103RB
Sounds great. Thanks! |
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. |
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? |
Maybe but I don't think the nRF51 devices have a SWJ-DP and I have seen it work on one of those. |
Doesn't the uC on the NUCLEO-F103RB which hints at an issue in my software have a SWJ-DP? |
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. |
Two more questions:
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. |
I think I implemented it that way because:
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. |
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.
I have seen no indication in your traces or my own that the Saleae actually knows how to decode SWD properly.
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.
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'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.
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. |
In SWDHost.spin, I see this defined:
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)? |
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. |
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. |
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! |
@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. |
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. |
@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. 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! |
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... The JTAGulator has 8 SWCLK falling edges and the SWDIO goes high on the 9th... 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... |
Two issues with the Saleae SWD analyzer. Trying to grok... |
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:
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. |
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.
This is awesome! You should push that change up. |
OK, we'll keep that as-is to avoid interfering with nRF51* devices.
Pushed! Let me know if you see anything problematic with it. I'll continue my testing with different targets tomorrow! |
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)
NUCLEO: SUCCESS! (Jumpers removed from the integrated ST-Link debugger)
Olimex LPC-P1343: SUCCESS!
nRF51822: SUCCESS! (We knew this one already when using the modified JTAGulator w/ 270 ohm resistors)
DEFCON 27 Badge (NXP MKL27Z64VDA4): SUCCESS! (We knew this one already using the stock JTAGulator, running @ 3V VCC)
|
@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? |
This is great news! Thanks for working with me over the last couple of weeks to whip the SWD code into shape. Much appreciated.
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 don't have any issue with that. |
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:
|
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
Edit: Done! |
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. |
I like that warning.
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.
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. |
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 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.
Yes! We can consider this thread closed. See you on the other one :) |
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! |
@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! |
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! |
This initial support includes the ability to perform an IDCODE scan via
ARM's Serial Wire Debug protocol.
Tested on:
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.
family.
Notes:
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.
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.
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:
at this time is 385kHz.