Security student here. Just wanted to say that while not everyone appreciates the firmware programming at such a low level....it is truly a dark art to me and I find it really interesting and always want to learn more.
Here my take. Not a pro, but still might find useful.
1. Learn basics of electricity, learn to use oscilloscope, logic analyzer. You don't necessary need to have knowledge to design complex PCBs (that's a separate skill and not easily attainable) but you need to be able to understand existing design on high-level and do some debugging. For example you wrote code which does some SPI to talk to some device but it does not work. You need to analyze electricity to understand what's going on in the wire.
2. Learn basics of assembly. You don't need to write your software in assembly, but you need to read it and write some little snippets if necessary.
3. Learn to read data sheets.
Modern MCUs and devices are really like libraries. You're using some interfaces, calling some functions and get some responses. Data sheets are library documentation.
Then it's only matter of time and experience. Most vendors supply their terrible libraries that you're supposed to use. Most vendors support some bad IDEs that you're supposed to use. Often you're forced to use Windows because not everyone supports Linux or macOS. It's not fun part and sometimes you can avoid it, but sometimes you can't.
Learn to read documentation in general. It's shocking how many people seem incapable of finding answers that are in official documentation but not on Stack Overflow.
The most humbling part is, there’s always another level down. I thought programming code for the Linux kernel was low-level, until I worked on a team where there was an entire separate MCU on the same package underneath the primary cores running Linux that booted and controlled the whole system. I thought that was low-level until I worked for a team building a similar chip and had to participate in the design and validation efforts for it. There is almost always a whole world beneath the level of abstraction any of us operate on. Beneath the software world are IP blocks, which are composed of digital logic circuits, which are composed of transistors, which are governed (if you get small enough) by quantum effects… reaching the bottom is nearly impossible; it’s very humbling.
This is especially true from a security standpoint. Many analysts are worried about XSS attacks and other such high-level techniques. C has an entire different class of vulnerabilities such as buffer overflows. And beneath that, there are countless vulnerabilities by exploiting properties of the physical hardware. Most industries choose to ignore these problems, because they’re very expensive to mitigate.