
Many newcomers and engineers learning embedded systems often feel confused halfway through their studies. They don’t know where to start, how to advance, or what level they are currently at in their learning journey.
To address these common concerns, today, an embedded engineer with 8 years of experience will share insights on what skills you need to master in the next phase of your embedded learning.
Career Directions for Embedded Engineers
Learning embedded systems can generally be divided into four directions:
1. Embedded Hardware Development: Familiarity with circuit knowledge, a thorough understanding of various common components, and mastery of analog and digital circuit design capabilities. Proficient in embedded hardware knowledge, familiar with hardware development and design patterns, and experienced in developing embedded hardware platforms using ARM 32-bit processors. Proficient in commonly used hardware design tools: Protel/PADS (PowerPCB)/Cadence/OrCad. Generally requires 4-8 layers of high-speed PCB design experience.
2. Embedded Driver Development: Proficient in Linux operating systems, system architecture, computer organization principles, and data structures. Familiar with embedded ARM development, and at least proficient in developing Linux character device drivers. Capable of porting development for microcontrollers and ARM embedded processors, understanding hardware schematics, and independently completing hardware driver debugging. Solid hardware knowledge is required, and the ability to write software drivers based on chip manuals.
3. Embedded System Development: Mastery of Linux system configuration, proficiency in processor architecture, programming environment, instruction set, addressing methods, debugging, assembly, and mixed programming; mastery of Linux file system creation, familiarity with various file system formats (YAFFS2, JFFS2, RAMDISK, etc.); familiarity with embedded Linux boot processes, and modification of Linux configuration files; mastery of kernel trimming, kernel porting, cross-compilation, kernel debugging, Bootloader programming, root filesystem creation, and the entire process of integrating and deploying Linux systems; familiarity with setting up Linux software development environments (cross-compiling library files and environment configuration, etc.);
4. Embedded Software Development: Proficient in the concepts and installation methods of the Linux operating system, basic commands, management configuration, and editors, including VI editor, GCC compiler, GDB debugger, and Make project management tools; proficient in advanced programming knowledge of C language, including functions and program structures, pointers, arrays, common algorithms, and library function usage, as well as foundational knowledge of data structures, including linked lists and queues; mastery of the basic ideas of object-oriented programming, as well as foundational knowledge of C++ language;
Proficient in program design under embedded Linux, and the embedded Linux development environment, including system programming, file I/O, multiprocessing and multithreading, network programming, GUI programming, and database; familiar with common graphical libraries for programming, such as QT, GTK, miniGUI, fltk, nano-x, etc.
The daily activities in companies vary based on their size. In larger companies, you might only be responsible for a module, requiring you to be proficient in that area. If the company is smaller, you may need to cover a broader range of responsibilities, including some hardware knowledge.
Having said all this, based on my personal experience, the biggest difference between embedded development and pure software development is:
Pure software focuses on learning a programming language, such as C, C++, Java, or even Python; essentially, a language is just a tool, much like learning English, French, or Japanese.
However, embedded learning involves both software and hardware. Simply put, it is about creating systems and products, emphasizing not just specific language tools, but also how to break down a product into implementable software and hardware components, as well as smaller units.
Many people ask, should I choose driver development or application development for future employment? It can only be said that it depends on your interest, and driver and application development are not entirely separate.
Specific reasons include:
1) What we refer to as drivers is not limited to hardware operation but also includes concepts like operating system principles, process sleep/wake scheduling, etc. To write a good application and effectively solve problems encountered in applications, everyone should understand these concepts.
2) The development path for applications is, in my opinion, about becoming proficient in the business. For example, in the telecommunications industry, IPTV industry, and mobile phone industry, understanding industry demands is crucial.
3) Working on drivers cannot simply be termed as “driver development” but rather as “developing underlying systems”. If done well, this can be applicable across various industries. For instance, if someone has worked for several years on mobile phones, IPTV, and video conferencing, these products may not differ for them because they only work on the underlying systems. When applications encounter problems they cannot solve, they can provide suggestions and tools from a kernel perspective. The development direction for underlying systems should be to become a technical expert.
4) In fact, there is no clear boundary between working on underlying systems and applications. Having underlying experience makes it feel more solid when transitioning to applications. With business experience, understanding the underlying systems can quickly form a cohesive team.
What Does the Embedded Linux Underlying System Include?
The embedded Linux system consists of four main components: bootloader, kernel, driver programs, and root filesystem.
It is a somewhat complex bare-metal program. However, understanding and writing this bare-metal program is not easy. The useful tools available on Windows have diminished our programming abilities. Many people start embedded development using ADS or KEIL. Can you answer these questions?
Q: When powered on, where does the CPU fetch instructions to execute?
A: Generally from Flash memory.
Q: However, Flash is usually read-only and cannot be directly written to. If global variables are used, where are they stored?
A: Global variables should be in memory.
Q: Who places the global variables into memory?
A: Friends who have used ADS or KEIL for a long time, can you answer this? This requires “relocation”. In ADS or KEIL, the relocation code is written by the companies that created these tools. Have you ever read it?
Q: Memory is so large; how do I know which address to read the “content originally in Flash” into memory?
A: This address is determined by the “linker script”. In ADS, there is a scatter file; KEIL also has a similar file. But have you studied it?
Q: You say relocation is copying the program from Flash to memory. Can this program read from Flash?
A: Yes, it must be able to operate on Flash. Of course, there are many more considerations, like setting the clock to make the system run faster, etc.
Let’s stop here with self-questions and answers. For the bootloader, there are actually three key points:
Operations on hardware require understanding schematics and chip manuals. This requires some hardware knowledge; you don’t need to design hardware but at least be able to read it. You don’t need to understand analog circuits, but you should understand digital circuits. This capability can be learned in school; two books, Microcomputer Principles and Digital Circuits, are sufficient.
If you want to fast-track, you might want to skip this part for now; if you don’t understand, just Google it or post a question. However, you must read the chip manual; don’t look for Chinese versions, just read the English ones. It will be very painful at first, but once you become familiar with the syntax and vocabulary, reading any chip manual will become easy.
② Understanding ARM Architecture Processors
Understanding ARM architecture processors can be done by reading Du Chunlei’s , which discusses assembly instructions, exception modes, MMU, etc. Only these three areas need to be understood.
③ Basic Concepts of Programs: Relocation, Stack, Code Segment, Data Segment, BSS Segment, etc.
The foundational concepts of programming can be learned from the classic . Unfortunately, this type of book is often considered a difficult read. Unless you are a super genius, you might want to avoid it. Instead, you can read Wei Dongshan’s .
For the bootloader, you can first read , and then write programs to experiment with various hardware components like GPIO, clocks, SDRAM, UART, NAND. Once you understand them, understanding u-boot will be much easier.
In summary, understanding hardware schematics and reading chip manuals require you to find resources yourself.
For those looking for a fast track, skip learning the kernel and go straight to writing drivers.
To become an expert, a thorough understanding of the kernel is essential. Note that understanding means having insights into scheduling mechanisms, memory management, file management mechanisms, etc.
Two recommended books: 1. Read thoroughly; please refer to the thinner version.
2. Selectively read ; read the sections that you want to understand.
Drivers consist of two parts: operations on the hardware itself and the framework of the driver program. Once again, hardware knowledge is essential; you need to understand schematics and read chip manuals, and practice more.
① Operations on the Hardware Itself
Regarding the driver framework, there are some books that introduce it. LDD3, i.e., , written by foreigners, introduces many concepts worth reading. However, its role is limited to introducing concepts. It can be used to familiarize yourself with concepts before starting.
② The Framework of Driver Programs
A comprehensive introduction to drivers can be found in Song Baohua’s . If you want to delve into a specific area, is definitely a 5-star recommendation. Don’t expect to read it cover to cover; it has over 1800 pages, divided into two volumes. Whenever you are unclear about a section, just flip through it. Any part can be elaborated on for 200-300 pages, very detailed. It analyzes the kernel source code with specific goals in mind. It uses Linux 2.4 as an example, but the principles are applicable to other Linux versions as well.
Try writing a driver for all the hardware involved in your development board. If you encounter problems, start with “painful thinking”; during this process, you will connect many unrelated pieces of knowledge, ultimately making it coherent.
Have you ever thought about these two questions:
Q: For products made with Linux, some are used for monitoring, some for phones, and some for tablets. After the kernel starts and mounts the root filesystem, which application should it start?
A: The kernel does not know or care which user program to start. It only starts the init application, corresponding to /sbin/init.
Clearly, this application must read a configuration file and start the user program (monitoring, manual interface, tablet interface, etc.). This indicates that the contents of the filesystem have some conventions, such as needing to have /sbin/init and a configuration file.
Q: Have you ever thought about who implements the printf function used in your hello world program?
A: This function is not implemented by you; it is implemented by the library function. When it runs, it needs to find the library.
This question indicates that the filesystem must also contain libraries. A simple self-question and answer session ends here. To delve deeper, you can look at busybox’s init.c to understand what the init process does.
Of course, you can also refer to the chapter on building root filesystems in .
Recommended Books for Learning Embedded Linux
1. Books on Hardware: Microcomputer Principles, Digital Circuits, standard textbooks from universities.
2. Books on Linux:, the foreign book
When developing drivers, you will definitely need to use kernel-related materials or need to cooperate with certain modules in the kernel. Therefore, you should understand how certain parts of the kernel are implemented, and ultimately, you should be able to grasp the overall framework of the Linux kernel.
These are all improvements that need to be summarized through your repeated development processes. If you do not summarize, you will always start from scratch (or you will always not understand why others’ code is written a certain way, and then just modify it to make it work), and that will be the end of it. This way, you will never improve, and eventually, you will feel like you know nothing and understand nothing.
Additionally, it should be noted that many people engage in Linux development without using the Linux system as their working platform. In this case, it is difficult to understand the implementation mechanisms of the Linux kernel and why certain methods are adopted.
If you have never used a Linux system, it is impossible to implement a project that aligns with the operational mechanisms of Linux. Even if your project succeeds, it will not be optimal or will not conform to the usage habits of Linux (including kernel extensions and application implementations).
1. The embedded system has entered the era of computing power~
2. While you stockpile goods, others quietly deliver; the MCU market is playing the Art of War.
3. A hands-on guide to running FreeRTOS on STM32F4!
4. Call for speakers for the Embedded Conference: Embedded AI, RISC-V, IoT, OS, and Software Testing.
5. How much current can a 0Ω resistor handle?
6. What to do if the crystal oscillator on the circuit board is not working?

Disclaimer: This article is a network reprint, and the copyright belongs to the original author. If there are any copyright issues, please contact us, and we will confirm copyright and pay remuneration or delete the content based on the copyright certificate you provide.