I'm an EE but spent most of my career as a computer engineer. I've never been as fond of writing software as I am of designing hardware, but I've certainly done plenty of the former.
For a rather long period of my career, I provided pre- and post-sales support to a microprocessor IP company that sold soft cores to be embedded in systems on chips. The HW folks, of course, wanted to get the constraints right so that Synopsys would generate a reasonable netlist and so that simulations would run correctly and they could see the machine boot and make successful bus transactions that covered every corner case.
The SW people just needed So Much More handholding. I easily spent time 10x more time with SWEs than HWEs as a result. A few trends were common:
- there was a sizeable contingent of SWEs who did not know how computers work, and had no interest in it. Buses, caches, etc, were all things that did what they did and there was no reason for a SWE to concern himself with them. This is not a recipe for embedded success.
- among those and probably among more, was a contingent who, in their life, had never once thought about what happens before main() or even were aware that anything happened before main()
- many had never given a moment's thought about how a program gets onto a machine
- few had experience with a non-OS environment, or even an unhosted environment
- concurrency: so many just didn't, couldn't get it
- on-chip peripherals were a mystery to most unless wrapped by someone else in friendly functions
- our architecture had an unfortunate quirk in that ISRs attached to interrupts above a certain priority level could not be written in C; They had to be in assembler, and you had to save and restore the registers you intended to clobber. This in theory was no great hardship, because usually with high priority interrupts, you wanted to get in and get out quickly, doing something simple. But the howls, HOWLS from developers about this limitation were endless
- SW folks did not like funky memory maps, disjoint memory spaces (like DSP "X/Y" memories) and other hardware tricks that segmented their view of the world.
- SW folks had a really hard time wrapping their heads around the idea that the hardware they were targeting might be buggy. After all, it was new, back from fab, and who knew what would be lurking there. But that never stopped any from trying, right out of the gate, to download their full multi-megabyte app to the target and being surprised that it didn't run. After all, it worked in the hosted simulator!
All that said, after all the moaning and groaning and a little bit of learning curve, they were able to produce working software, some of which did amazing things.
I guess my point is that in order to do embedded systems, you don't need to be an EE, you don't have to be comfortable with an oscilloscope, but you do need an awareness of how a computer system is organized. Computer Science programs did not seem to be teaching this. In fact, the most elite CS programs preferred to teach CS as a mathematics discipline, divorced from greasy, dirty hardware entirely. If graduates from such programs could not get off that mental track, they could not successfully program embedded systems.
Anyway, my $0.02.