Today most semiconductors cannot function without embedded code - from ARM core to DSP engine, software has become as significant as the silicon it is running on.
Embedded programming has transformed from a relatively low-level basic activity into a high-level heterogeneous multicore programming challenge. Early days, at low complexity levels there was little, or no code embedded onto an IC. If there was, most of it had to be loaded at startup time from an external memory. Today the challenge is inherently more complex. The effort to write, test and validate the code for a complex IC like an edge-based vision chip is probably equal to the design of the circuitry on the chip. Added challenges related to security and integrity make this even more challenges as does the requirement to cover multiple modes of operations (for instance executing a task on a low-power core rather than a high-performance core). The environment for developing code for the different platforms has been improving: (open source) stacks for both generic and specific applications, ranging from machine learning to specific pattern recognition packages. The complexity that is growing brings in special disciplines such as TinyML, a fast growing area in the field of deep learning.