I am working on coding stuff I like as escape for the absurdity of modern software. I make little games, stuff for 8 bit systems etc. Stuff that is as far away from anything modern , especially the hell of node, next, devops and ‘web frameworks’ as I possibly can. It works. It’s very relaxing, like a bonsai tree.
+1 for embedded software. I work for an IoT company and the web and app devs think LLMs are the saving grace of the universe. The firmware team just keeps chugging along, ignoring the noise, debugging hard problems, and writing unsexy low level code.
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.
Yeah, programming used to be excellent and that’s not nostalgia as I still write MSX, Amiga and Delphi (win/lin) software. Now, with modern stacks, I just hate all of it really. I do it fulltime for work with nextjs (and all the du jour stuff that literally changes every few months and makes life easier: secret it doesn’t at all) but we are transitioning everything to my Common Lisp dsl; in one year even my work software will be a pleasure again. Stuff I should’ve done 20 years ago but I drank this modern tooling koolaid; it’s more akin to the layers of hell.