For I2C it's always important to verify signal integrity with an oscilloscope. You can't do that by looking at source code or a logic analyzer trace. I do have a Siglent SDS 1104X-E to do this, but once signal integrity is verified, I do the rest with a Logic Analyzer. I have a few of the USD5 Saleaeae clones and use them with Sigrok / Pulseview (Gorgeous program, quite a shame it's struggling to keep it's head above the mowing field). I find the big scope probes very cumbersome to use. I like using breadboards with uC modules in DIP format (Bare crystals on breadboards are a huge reliability problem, but the small uC breakout boards work wonderfully). It's easy to use some short dupont wires between the LA and the breadboard. I also find that a big 4k PC monitor with mouse and keyboard is a much more convenient user interface for an LA then an oscilloscope screen. Zooming, scrolling is quicker, you have many more channels (16 with my Kingst LA2016, My EUR60 upgrade from the Saleaeaea clones). You can also enter signal names & labels with a normal keyboard, save and recall configurations from disk, have many more signal analyzers.
Another debugging technique I use regularly is to spit out some serial data (uart, spi, I2S, whatever peripheral is available, even bitbanging an I/O pin) and then catch that data with the logic analyzer too. This lets you build a correlation between the other signals and what your software is doing. For example, you can spit out a particular byte each time an ISR is triggered, and use different bytes for different ISR's.
You can also toggle an I/O bit when the uC is "idle". Whenever this bit stops toggling, the uC is doing "something" (such as servicing an ISR).
I'm no expert, and have not used a "real" debugger much. Stepping though code is also a very limited technique. It's very slow, and it completely disrupts timing of everything. Spitting out some bytes and catching it with a LA gives you the opportunity to trace backwards when you've found "weird behavior", and then go searching for what happened just before the fault.
With my Siglent, I can probably see the bytes of I2C fairly easily, but Sigrok / Pulseview has decoders you can stack on top of the bare I2C bytes. I once examined some low-speed USB signals this way, and the amount of information it reveals immediately is amazing. It shows T-states, keep alive packets, addressing, where data is in packets, checksums and whether they are good or not and much more then I can recall right now.