Skip to content

SVD2LLDB Guided Example#183

Open
iCMDdev wants to merge 20 commits intoswiftlang:mainfrom
iCMDdev:lldb-guide
Open

SVD2LLDB Guided Example#183
iCMDdev wants to merge 20 commits intoswiftlang:mainfrom
iCMDdev:lldb-guide

Conversation

@iCMDdev
Copy link
Copy Markdown
Contributor

@iCMDdev iCMDdev commented Dec 23, 2025

This draft PR will add an example on how to use LLDB with Swift Embedded (including SVD2LLDB). I decided to create this draft PR and ask for your thoughts & feedback.

Would love to hear what you think, especially regarding:

  • How this should be organized (Should it be embedded in one of the current examples? Or, perhaps, a new guide?)
  • What board should be used?
  • What should the example code do? For example, debugging a timer control register (like in the SVD2LLDB docs)

@iCMDdev iCMDdev marked this pull request as draft December 23, 2025 14:24
@iCMDdev
Copy link
Copy Markdown
Contributor Author

iCMDdev commented Dec 23, 2025

Sorry, seems I forgot to click on the draft button

@iCMDdev iCMDdev changed the title SVD2LLDB Guide Example SVD2LLDB Guided Example Dec 23, 2025
@xtremekforever
Copy link
Copy Markdown
Contributor

So you added a new link to an LLDBGuide but where's the guide itself?

@iCMDdev
Copy link
Copy Markdown
Contributor Author

iCMDdev commented Dec 24, 2025

@xtremekforever I added the markdown now. I didn't create an example yet - this is why I marked it as a draft PR, sorry. Maybe this was better suited as an issue instead of a PR until I finish it - I opened it so that we could discuss and track progress on it.

Either way, what board / example do you think would be best?

Added a tutorial for using LLDB with Swift Embedded code, including prerequisites and installation instructions.
Note: RP2040 should be almost the same; there's only one register that does not exist - `pads_bank0.gpio[pin].iso`
@iCMDdev iCMDdev marked this pull request as ready for review February 20, 2026 14:46
@iCMDdev
Copy link
Copy Markdown
Contributor Author

iCMDdev commented Feb 20, 2026

I have written the guide and it should be almost ready. The guide was designed for Raspberry Pi Pico (RP2040/RP2350) boards (via conditional compilation using Swift Package traits).

The tutorial guides readers through using LLDB to identify and fix some bugs in a sample I2C embedded app written with Swift MMIO. It is a simple example in which an I2C device, represented by the Pico's i2c0 interface, is connected to a hypothetical, special I2C peripheral memory, emulated by the i2c1 interface.

iCMDdev and others added 3 commits March 3, 2026 20:19
Corrected typos and enhanced clarity in LLDBGuide.md.
Updated wording for clarity and corrected minor typos in the LLDBGuide documentation.
@heckj
Copy link
Copy Markdown
Member

heckj commented Mar 4, 2026

👋 @iCMDdev - I read through the article/tutorial, and would like to provide feedback, but I'll preface this with a very definite I AM NOT AN EMBEDDED DEVELOPER caveat. There may be some baseline expected knowledge that I'm stumbling over.

I made notes as I read through the article, trying to bundle them under section headings. Quite a lot was fairly direct to follow, but there were some places where I was really stumped, unclear on what or how I should do something, or what I should know. In several places, the order of the information presented it later in the section, so I ended up having to read forward, backward, and forward again to get a sense of what I could/should do in each section.

As a general rule, I'd highly suggest removing any of the phrases "simply" or "just" - I've seen that used to make it sound easier or less imposing, but without knowing a lot of this detail already, I felt really silly and awkward.

I love the overall run through the content - using LLDB (through OpenOCD I guess), but when you were presenting the bugs and what was happening, my lack of embedded knowledge and expectations may be very out of whack. I didn't understand many of the intuitive leaps that you made in the writing, although once you made them I could back track and find evidence of bits of it in the presented examples.

  • prerequisites are jargon heavy - talk about both GDB and LLDB, and something about an OpenOCD thing as an alternative path - but how (or why) is unclear at this point.
  • When you mentioned SVD2LLDB, it was later in the section but kind of needed to be introduced up front from what I read. The link for the installation is points to its docs, but those docs show how you load and use SVD2LLDB, not how to install it - so I was at a loss on what I'd need to do there, and it seems a critical part of what we'll touch on.
  • "initial board setup"
    • At end of the section I'd have no idea how to connect up the SWD pins as the instructions ask, and there's no labels in the diagram above it - I'm not sure if the diagram was meant to help there or not. Maybe my lack of basic experience here.
  • "uploading the firmware"
    • I found the last sentence almost contradictory - talking about both GDB and LLDB, and I wasn't sure where it was going

The current example firmware is saved in RAM rather than Flash, so if you unplug your board, you will need to reflash it.
- (If it didn't go into flash, why would I need to reflash it?) I'm assuming this is an embedded jargon thing that I'm not quite getting - but I get the idea, the thing you uploaded is ephemeral.

  • "Attaching LLDB"
    • opens with a warning - but haven't a clue what version is late enough that I need to update. Can any more details be made so I can figure out, other than "it don't work!"
    • I'm guessing from the article about openOCD that it's a bit of code that you can run somewhere, but I'm not sure where that is - is this another RaspberryPi that's set up and connected somehow and forwarding port details? Is that running on my mac? On a Pi? Somewhere else?
    • I'm only barely effective with LLDB, so how to use "thread sel" command, other than the example explicitly provided, isn't meaningful to me. Is there an implication to seeing assembly in one thread, what appears to be C/swift code in another?
    • The instructions are jumbled a bit at the very end of this section, and I'm not sure how they relate to using LLDB earlier. Was the process interupt what let us see the code earlier?
  • "Finding bugs with LLDB"
    • implied use frame sel N to select the call stack you want to inspect
  • "Setting a breakpoint..."
    • just coming clear that reflashing the code onto the board makes it immediately run. Nice detail that you can set a breakpoint BEFORE this happens
    • I have no idea how to identify some of the code as Bootloader code vs. anything else
  • "Investigating the second bug"
    • talks to using Control-C to to interupt the code - I'm guessing we're working with at least two terminals, and I'm not clear on which one and where I'd want to invoke that. I'd have to experiment to learn
    • the mismatched registers I get as a bug, but honestly I wouldn't have a clue on what's 'right' and how to resolve it as the tutorial asks me to do.
  • "Finding and fixing the last bug"
    • unclear why I need to remember the reset value is 0x65 - and I had no idea as a non-embedded developer.
    • It's later asserted that the i2c1 register has this value, but I'm not seeing it in the examples and wouldn't know how to look right off the bat. I'm not sure if I was supposed to get that from the decode of the complex register or not.

@iCMDdev
Copy link
Copy Markdown
Contributor Author

iCMDdev commented Mar 6, 2026

Hi @heckj, thanks a lot for the feedback! I would also like to preface this by saying I am not an expert embedded developer either, but rather a student still learning. And this is probably my first time writing documentation this big for a project of this nature, so your advice is greatly appreciated!

First of all, I'd like to note that I added a paragraph withmore information about the setup at the beginning of this guided example, which may make this project easier to digest before reading the prerequisites. I am not sure how I should modify the prerequisites - was striking for a match between keeping things short (explaining in more detail later).

Regarding this:

When you mentioned SVD2LLDB, it was later in the section but kind of needed to be introduced up front from what I read. The link for the installation is points to its docs, but those docs show how you load and use SVD2LLDB, not how to install it - so I was at a loss on what I'd need to do there, and it seems a critical part of what we'll touch on.

I changed the link to the correct build instructions.

Regarding your other notes, I made some other changes based on your descriptions, so please let me know what you think! I described them below.

1. Removing "simply" / "just"

As a general rule, I'd highly suggest removing any of the phrases "simply" or "just" - I've seen that used to make it sound easier or less imposing, but without knowing a lot of this detail already, I felt really silly and awkward.

That is definitely not what I was going for, I made a few changes, let me know if this sounds better now.

2. Initial board setup - SWD connection

  • "initial board setup"
    • At end of the section I'd have no idea how to connect up the SWD pins as the instructions ask, and there's no labels in the diagram above it - I'm not sure if the diagram was meant to help there or not. Maybe my lack of basic experience here.

On the SWD debug probe side, this usually depends on the board and the users' hardware debugger. I tried to clarify this by saying "After you made the connections above, you will need to connect a debugger to the board's SWD pins. Refer to your hardware debugger's documentation for more info". The board's 3 debug pins that need to be connected are those marked as "DEBUG".

3. Uploading the firmware

The current example firmware is saved in RAM rather than Flash, so if you unplug your board, you will need to reflash it.

  • (If it didn't go into flash, why would I need to reflash it?) I'm assuming this is an embedded jargon thing that I'm not quite getting - but I get the idea, the thing you uploaded is ephemeral.

Yeah, the idea is indeed that the code is ephemeral the way it's saved currently (RAM memory is erased when the board's power supply is cut), though we could modify the linker scripts to save the code in flash memory (which is persistent). I changed the wording a bit.

4. Attaching LLDB

  • opens with a warning - but haven't a clue what version is late enough that I need to update. Can any more details be made so I can figure out, other than "it don't work!"

Sorry, yes, this is meant to be updated. This depends on an OpenOCD patch that I submitted and is yet to be merged.

  • I'm guessing from the article about openOCD that it's a bit of code that you can run somewhere, but I'm not sure where that is - is this another RaspberryPi that's set up and connected somehow and forwarding port details? Is that running on my mac? On a Pi? Somewhere else?

Yes, OpenOCD is the program that connects your hardware debugger (an extra piece of hardware connected to your board, like a dongle) to your software debugger, i.e. LLDB. It provides interface that LLDB can use, that is, the GDB remote debug port. I also made some changes to clarify this.

  • I'm only barely effective with LLDB, so how to use "thread sel" command, other than the example explicitly provided, isn't meaningful to me. Is there an implication to seeing assembly in one thread, what appears to be C/swift code in another?

I added a few words about Swift vs assembly here and here. Let me know if you want me to clarify this further - the idea is that one thread is unused (running the chip's own ROM code), while the other one is running our Swift code (for which we have debug symbols + the source code itself).

The instructions are jumbled a bit at the very end of this section, and I'm not sure how they relate to using LLDB earlier. Was the process interupt what let us see the code earlier

I'm not exactly sure which instructions you're referring to, but yes, when the code execution is interrupted, we can see the code line(s) where the program was stopped - some commands such as frame sel / frame info / thread info display them. You can also use the source list command.

5. Setting a breakpoint on our app's entrypoint

  • I have no idea how to identify some of the code as Bootloader code vs. anything else

I did describe this previously but I am not sure how to specify this without repeating myself; I would love to hear your suggestions.

6. Invesigating the second bug

  • talks to using Control-C to to interupt the code - I'm guessing we're working with at least two terminals, and I'm not clear on which one and where I'd want to invoke that. I'd have to experiment to learn

This is the terminal in which you're running LLDB. I made some changes to clarify the setup here and here. There is only one other terminal, running OpenOCD.

  • the mismatched registers I get as a bug, but honestly I wouldn't have a clue on what's 'right' and how to resolve it as the tutorial asks me to do.

To be clear, the problem is that i2c0 is sending data to one address, while the memory device is configured to listen on a different one. As long as these addresses are equal, everything works.

7. Finding and fixing the last bug

  • unclear why I need to remember the reset value is 0x65 - and I had no idea as a non-embedded developer.

This was meant as "remember for later". I made some changes, tried to clarify this.

  • It's later asserted that the i2c1 register has this value, but I'm not seeing it in the examples and wouldn't know how to look right off the bat. I'm not sure if I was supposed to get that from the decode of the complex register or not.

It is visible in the decode output (see the second line below):

(lldb) svd decode i2c1.IC_CON --read --visual
I2C1.IC_CON: 0x0000_0065 <-- this is the address

                               ╭╴SPEED
                             ╭╴IC_10BITADDR_MASTER
                           ╭╴IC_SLAVE_DISABLE
                         ╭╴TX_EMPTY_CTRL
                       ╭╴STOP_DET_IF_MASTER_ACTIVE
                       ┴ ┴ ┴ ┴ ┴─
0b00000000000000000000000001100101
                        ┬ ┬ ┬ ┬  ┬
                        ╰╴RX_FIFO_FULL_HLD_CTRL
                          ╰╴STOP_DET_IFADDRESSED
                            ╰╴IC_RESTART_EN
                              ╰╴IC_10BITADDR_SLAVE
                                 ╰╴MASTER_MODE

[10:10] STOP_DET_IF_MASTER_ACTIVE 0x0
[9:9]   RX_FIFO_FULL_HLD_CTRL     0x0 (DISABLED)
[8:8]   TX_EMPTY_CTRL             0x0 (DISABLED)
[7:7]   STOP_DET_IFADDRESSED      0x0 (DISABLED)
[6:6]   IC_SLAVE_DISABLE          0x1 (SLAVE_DISABLED)
[5:5]   IC_RESTART_EN             0x1 (ENABLED)
[4:4]   IC_10BITADDR_MASTER       0x0 (ADDR_7BITS)
[3:3]   IC_10BITADDR_SLAVE        0x0 (ADDR_7BITS)
[2:1]   SPEED                     0x2 (FAST)
[0:0]   MASTER_MODE               0x1 (ENABLED)
(lldb)

@iCMDdev
Copy link
Copy Markdown
Contributor Author

iCMDdev commented Mar 9, 2026

The OpenOCD patch was merged yesterday in the following commit: openocd-org/openocd@22e1e1b.

Copy link
Copy Markdown
Member

@heckj heckj left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The updates for explanations in the guide are great! I ran through the whole thing again this morning, and stumbled a bit with the back and forth between the tenses (jumping between we/our and you/your) - so I've made a (large) set of suggestions for changing most of the wording to use you/your, which matches the style that's common in Swift's documentation.

I may not have hit them all, but hopefully you get a sense of it. The place where I explicitly left "we" alone was in the earlier part of the article where "we" seemed to imply this project/the community and was providing recommendations.

I also dropped some of the "You can ..." to be more direct in getting to the action of what the guide is asking the reader to do. Read through with these changes, see what you think. I tried to not make any changes that significantly removed your voice from the writing, while making it more direct and consistent.



### Installing Swift, LLDB and SVD2LLDB
> Note: Embedded Swift is experimental. Public releases of Swift do not support Embedded Swift, yet. See <doc:InstallEmbeddedSwift> for details.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For this guide, I'd suggest minimizing talking about how Embedded Swift is experimental - anyone popping in here today already has a sense of that, and the key detail in this note is that public releases of Swift don't include Embedded Swift, so you need to install it directly through an open source toolchain. I don't think you need both the call out and the first paragraph, as they're redundant.

The bonus of stripping this note also gives this article better longevity - you won't need to explicitly strip this later when it advances.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense. This warning is also present in these other (currently published on swift.org) pages:

Should we remove it from the Pico example? I think the first two make sense, since these are pages with general information, but once the reader approaches the precise guided examples, they already know this.

Moreover, this warning isn't present in the macOS Guided Example or the STM32 one.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we need to go out of our way on this topic to normalize it - it'll be more places to switch once it is part of a release, my suggestion for this guide just reduces that future workload by 1 ;-)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW we should only say this once in the entire documentation catalog. Each article repeating it isn't helpful.

Additionally, that warning was introduced when embedded would crash the compiler extremely frequently. It's no longer a super helpful warning, as we're well on the way to productizing.

Copy link
Copy Markdown
Contributor Author

@iCMDdev iCMDdev Mar 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I removed it from the current guide (can mark this as solved). So, do you want me to keep the others, remove them in another PR or should I rather remove them here?

Additionally, that warning was introduced when embedded would crash the compiler extremely frequently. It's no longer a super helpful warning, as we're well on the way to productizing.

It does indeed feel very robust and much less experimental nowadays :)

Copy link
Copy Markdown
Member

@heckj heckj left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The updates for explanations in the guide are great! I ran through the whole thing again this morning, and stumbled a bit with the back and forth between the tenses (jumping between we/our and you/your) - so I've made a (large) set of suggestions for changing most of the wording to use you/your, which matches the style that's common in Swift's documentation.

I may not have hit them all, but hopefully you get a sense of it. The place where I explicitly left "we" alone was in the earlier part of the article where "we" seemed to imply this project/the community and was providing recommendations.

I also dropped some of the "You can ..." to be more direct in getting to the action of what the guide is asking the reader to do. Read through with these changes, see what you think. I tried to not make any changes that significantly removed your voice from the writing, while making it more direct and consistent.

Co-authored-by: Joseph Heck <j_heck@apple.com>
iCMDdev added 3 commits March 10, 2026 20:35
Apply suggestions from code review:
- More consistency between "we/our" and "you/your"
- Add correct file link(s)

OpenOCD is a program that connects to your hardware debugger, providing an interface that LLDB uses to connect and control your board.

> Note: OpenOCD had a bug which may have prevented LLDB from connecting to your board. Ensure you are using the latest version available.
Copy link
Copy Markdown
Contributor Author

@iCMDdev iCMDdev Mar 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
> Note: OpenOCD had a bug which may have prevented LLDB from connecting to your board. Ensure you are using the latest version available.
> Note: OpenOCD had a bug which may have prevented LLDB from connecting to your board, which was fixed in commit [22e1e1b](https://review.openocd.org/q/22e1e1b33e844c343eb3f24d24f630e2471d2b27). Ensure the version you are using includes this patch.

Note to myself: this should be updated to the latest state when this guide is published (that is, include a version number rather than a commit hash, if available). Current state is that the OpenOCD patch was merged in the aforementioned commit, but there's no tagged release containing it yet (maintainers said version 1.0.0 should be tagged soon / asap).

Also, this commit is not yet present in the Raspberry Pi fork (for the Pico / RPi Debug Probe) - linking raspberrypi/openocd#147 for reference.

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