Lecture Notes on Microcomputer Principles and Interface Technology for Embedded Systems

The field of embedded systems encompasses a wide range of topics, and there are many choices regarding what and how to teach in the “Microcomputer Principles and Interface Technology” course. Here, I will introduce my approach.

1. Overview of the Main Knowledge Points

First Level Knowledge Points

(1) Von Neumann Architecture; (2) Embedded Hardware Systems; (3) Embedded Software Systems;

Second Level Knowledge Points of Hardware

(2.1) CPU/Core; (2.2) Memory; (2.3) Bus (Internal Chip Bus); (2.4) Peripherals;(2.5) Interrupts/Exceptions;(2.6) Stack;(2.7) JTAG;(2.8) DMA;

Second Level Knowledge Points of Software

(3.1) Instruction Set Architecture;(3.2) Compiler Toolchain;(3.3) BootLoader;(3.4) C Language;(3.5) Software Layer Structure;

2. Overview (1)

A microcomputer refers to a microcomputer. Here, the term computer refers to electronic computers derived from the Von Neumann architecture.

Therefore, the overview section first introduces the main characteristics of the Von Neumann architecture, which are: binary, stored-program control, and sequential execution. The core concept is stored-program control, which introduces concepts such as programs, controllers, and memory.

A program consists of instructions (specific binary sequences), and the CPU/Core, composed of a controller and an arithmetic unit, continuously “fetches instructions, decodes instructions, and executes instructions,” which is the core of the computer.

From an application perspective, computers can be divided into general-purpose computers and dedicated computers (i.e., embedded systems).

The hardware and software of embedded systems are custom-designed for specific applications, optimized for specific performance metrics, and differ in structure from general-purpose computers. The terminology and technical content covered also differ. Therefore, whether the content is oriented towards general-purpose computers or embedded systems will affect the textbook content and learning path.

This article focuses on embedded systems. Embedded systems are divided into hardware systems and software systems, with an emphasis on explaining the working principles of hardware systems.

First Level Knowledge Points

(1) Von Neumann Architecture; (2) Embedded Hardware Systems; (3) Embedded Software Systems;

3. Overview (2)

The hardware system of a single-chip microcomputer (the internal circuit structure of the microprocessor chip) can be roughly divided into:

CPU/Core, Memory, Bus, and Peripherals, with other components including power supply, clock, debugging interfaces, etc.

The CPU/Core continuously executes the process of “fetching instructions, decoding instructions, executing instructions.”

Instructions are binary data that the CPU/Core can recognize and execute specific actions. There are various instruction set architectures, including: x86/amd64, ARM Cortex-M/Cortex-A, 8051, AVR, RISC-V RV32/RV64, etc.

Existing instruction set architectures are divided into Complex Instruction Set Computer (CISC) and Reduced Instruction Set Computer (RISC). The instruction set architectures used in embedded systems generally belong to the RISC category (such as ARM, RISC-V). RISC-V is an open-source instruction set architecture, and it is recommended for study.

Instructions are stored in memory, and the CPU/Core fetches instructions from memory via the bus. The instructions are interpreted and executed within the CPU/Core.

In RISC architectures, instructions can generally be categorized into arithmetic, jump, LOAD/STORE, and others.

Arithmetic and jump instructions are executed internally within the CPU/Core.

For LOAD/STORE instructions, the CPU/Core reads and writes to memory storage units and I/O registers of peripherals mapped to the bus, exchanging data with the general-purpose register set within the CPU/Core.

The CPU/Core accesses I/O registers in peripherals through LOAD/STORE instructions, affecting the behavior of the internal circuits of the peripherals, thereby controlling the logic levels of the chip pins associated with the peripherals, allowing software (instructions) to control hardware (external circuits of the chip).

Second Level Knowledge Points of Hardware

(2.1) CPU/Core; (2.2) Memory; (2.3) Bus (Internal Chip Bus); (2.4) Peripherals;

Second Level Knowledge Points of Software

(3.1) Instruction Set Architecture;

Other Terminology

Processor Chip; Chip Pins; Peripheral Circuits; Instructions;

4. CPU/Core

The CPU/Core is a digital circuit.

The behavior of the CPU/Core:

(1) Continuously “fetches instructions, decodes instructions, executes instructions,” unless it encounters:

(2) A Reset signal, which restarts from a specific address;

(3) …

How to fetch instructions? PC register; memory bus;

How to decode instructions? Instruction set specification; instruction format;

How to execute instructions? Instruction set specification; analysis by instruction category;

Third Level Knowledge Points of CPU/Core

(2.1.1) PC Register; (2.1.2) General Register Set (Register File); (2.1.3) Arithmetic and Logic Unit (ALU); (2.1.4) Stack Pointer Register (SP);

5. Interrupts

The behavior of the CPU/Core:

(1) Continuously “fetches instructions, decodes instructions, executes instructions,” unless it encounters:

(2) A Reset signal, which restarts from a specific address;

(3) An interrupt, which pauses the execution of the current instruction stream, jumps to the interrupt service routine, and continues to “fetch instructions, decode instructions, execute instructions” until it encounters an interrupt return instruction to return to the breakpoint and continue execution;

(4) …

(The detailed description of the following content is omitted)

Definition of Interrupts

Interrupt Handling Process

Interrupt Management

Interrupt Entry (Interrupt Vector Table)

Second Level Knowledge Points of Hardware

(2.5) Interrupts/Exceptions;

Third Level Knowledge Points of Interrupts

(2.5.1) Interrupt Vector Table;

Other Terminology

Interrupt Request; Interrupt Response; Interrupt Handling; Interrupt Return; Interrupt Source; Interrupt Enable; Interrupt Nesting; Breakpoint; Context Protection; Context Restoration; Interrupt Vector Table;

6. Stack

Where is the breakpoint saved during an interrupt? Where is the RF content saved during context protection?

This leads to the stack.

(It can also be introduced from function calls)

(The detailed description of the following content is omitted)

Concept of Stack

Function of Stack

Stack Operations

Second Level Knowledge Points of Hardware

(2.6) Stack;

7. Instructions and Programming

Where do the instructions corresponding to the application program come from?

  • Binary instructions can be directly written (burned) into the instruction memory.

  • Source programs can be written in assembly language format on a host computer, then converted into executable program files (cross-compiled) using an assembler and linker, and then burned or loaded.

  • Source programs can be written in compiled high-level languages (such as C language), then compiled (compile) and linked (link) into executable program files, and then burned or loaded.

  • Source programs can be written in interpreted high-level languages (such as Python), copied to the external storage of the embedded system (such as an SD card), and then the embedded system runs an interpreter (such as MicroPython) to interpret the source code into executable instructions.

How to burn or load?

  • Programs can be burned into instruction memory through debugging interfaces like JTAG using the JTAG module on the processor chip;

  • Alternatively, a BootLoader program can be run on the processor chip, allowing the host computer to download the application program to the processor’s Flash or RAM via serial or network interfaces;

  • Or executable program files can be copied to the external storage of the embedded system (such as an SD card), and then the embedded system runs a loader program to write the instructions into RAM.

Second Level Knowledge Points of Hardware

(2.7) JTAG;

Second Level Knowledge Points of Software

(3.2) Compiler Toolchain; (3.3) BootLoader;

Third Level Knowledge Points of Compiler Toolchain

(3.2.1) GCC Toolchain; (3.2.2) OpenOCD; (3.2.3) Keil IDE;

Other Terminology

ELF File Format; LD Link Configuration File; GCC Compilation Options;

8. Memory

Memory can be categorized into various types based on implementation technology, including ROM, SRAM, DRAM, Flash (NOR Flash, NAND Flash), EPROM, EEPROM, etc. Optical discs, hard drives, and tapes are also classified as memory.

From the perspective of whether the CPU/Core can directly access memory via the bus, memory can be divided into internal memory and external memory.

The CPU/Core provides address signals and control signals on the system bus, and memory that can respond to bus signals with data is considered internal memory.

The CPU/Core accesses peripheral modules via the system bus, reading and writing to I/O registers on the peripheral modules, while the peripheral modules are responsible for reading and writing the contents of memory, which is referred to as external memory.

Internal memory can be on the same chip as the CPU/Core or external to it.

External memory modules are connected to the system bus through memory controller modules that act as bus converters (such as DRAM controllers, SPI NOR Flash XIP controllers); some chips directly output bus signals from pins (such as 8051), connecting to SRAM chips outside the processor chip.

External memory is generally outside the processor chip, but it can also be found on-chip (such as certain on-chip EEPROMs used for storing configuration data).

ROM-type memory retains its contents after power loss, while RAM does not.

If a program needs to run in RAM for speed, a segment of code must first be executed to read the executable program instruction segment from Flash or external memory into RAM, and then jump to the RAM address to run. This code is referred to as a BootLoader or (operating system) loader program.

Processor chip manuals generally include a memory mapping table (Memory Map), which lists the modules that the CPU/Core can access directly via the bus, along with the assigned addresses (physical addresses).

Third Level Knowledge Points of Memory

(2.2.1) Internal Memory; (2.2.2) Memory Mapping Table (Memory Map);

9. Relationship Between C Language Source Code and Chip Instructions and Memory

Location of Global and Local Variables

  • During compilation and linking, global variables and locally defined variables with the static modifier are allocated address units in fixed RAM space; ordinary local variables within functions are allocated to general registers in the Register File (RF) whenever possible, and when RF registers are insufficient, dynamic address units are allocated in the stack (the stack is in RAM).

  • Variables allocated in RF registers can be operated directly during calculations; variables allocated in RAM need to be loaded into RF first, operated on, and then the results stored back in RAM.

  • Variables allocated in RF do not have address pointers.

Function Calls

  • During compilation, the compiler automatically adds statements for parameter passing and context protection/restoration for function calls.

  • If source code is written in assembly language, this part of the work must be done by the programmer. (The assembler only translates assembly language into machine language and does not add code).

  • Parameter passing uses RF, and may also use the stack; context protection and restoration often use the stack.

  • The return address of a function is saved in a register for some instruction set architectures, while others save it on the stack.

Link Configuration Files

  • During linking, the link configuration file specifies the memory address regions for the code and data segments.

Therefore, analyzing the relationship between C language code and the compiled instructions/disassembled code helps to understand the behavior of the CPU/Core and the storage locations of variables, as well as to conduct code optimization.

Second Level Knowledge Points of Software

(3.4) C Language;

Third Level Knowledge Points of C Language

(3.4.1) Variables; (3.4.2) Function Calls;

Other Related Content

Usage of GCC Toolchain; Usage of IDE; Makefile;

10. Peripherals (1)

Peripherals are dedicated digital circuits used for interaction between the CPU/Core and external circuits or to achieve specific functions.

Common peripherals covered in textbooks include: GPIO, timers/counters, serial ports (UART), while others like ADC, DAC, I2C, SPI, I2S, Ethernet, etc., depend on the selected chip and the instructor’s discretion.

The CPU/Core accesses I/O registers in peripherals through LOAD/STORE instructions, affecting the behavior of the internal circuits of the peripherals, thereby controlling the logic levels of the chip pins associated with the peripherals, allowing software (instructions) to control hardware (external circuits of the chip).

Third Level Knowledge Points of Peripherals

(2.4.1) GPIO; (2.4.2) Timer; (2.4.3) Serial Port (UART);

11. DMA

When the data read/write speed of peripherals is too slow and affects the performance of the CPU/Core, a task can be offloaded to a peripheral called DMA, which completes the exchange of content between the target peripheral and a specified memory space, and then notifies (via interrupt) the CPU/Core to process the data in memory.

However, since the DMA module also accesses peripherals and memory via the system bus, it competes with the CPU/Core for bus control. Therefore, a bus arbiter must be added to the bus, and the LOAD/STORE bus interface of the CPU/Core must support hold signals, meaning the bus type needs to change from synchronous to semi-synchronous.

Note: Even without a DMA module or other bus master modules, if the data read/write response of the memory module or peripheral module cannot keep up with the timing of the CPU/Core, the LOAD/STORE bus type must also change from synchronous to semi-synchronous. This will result in the time taken for the CPU/Core to execute an instruction being uncertain.

Second Level Knowledge Points of Hardware

(2.8) DMA;

Third Level Knowledge Points of Bus

(2.3.1) Synchronous Bus; (2.3.2) Semi-Synchronous Bus;

12. Software Layering

Bare-Metal Programs

When functionality is simple, all code is written by the same application designer, and the application code is executed immediately after the chip starts.

This type of program is called a bare-metal program.

The basic program structure of bare-metal programs can be divided into two types: (1) Polling (no interrupts); (2) With interrupts;

RTOS (I)

When functionality becomes complex and multiple independent tasks need to run concurrently, some application-independent code is separated for task management and scheduling, coordinating the competition for hardware resources among tasks. This part of the code forms the Real-Time Operating System (RTOS) (or uOS, micro operating system). Other application-related code is divided into individual tasks, collectively referred to as application programs.

Simple RTOS code and application code are distributed in the same storage space, and the application code calls RTOS system functions directly.

Generally, during development, these two parts of code need to be linked together (RTOS code can be provided as a compiled library file) and burned together.

At this point, the relationship between the task codes and the RTOS code can be understood as multiple threads.

On the hardware side, the chip needs to provide a hardware timer specifically for RTOS use. (This is often referred to as the SysTick timer in ARM Cortex-M terminology).

RTOS (II) (Based on MPU)

When there is a desire for a certain degree of isolation between RTOS code and application code or between different tasks’ application codes (for example, a certain task’s code cannot read/write RTOS variable content), the chip hardware needs to add MPU modules, privileged modes, and software interrupts to isolate access between code segments.

At this point, RTOS code and application code are still distributed in the same storage space. Generally, these two parts of code still need to be linked together.

RTOS (III) (Based on MMU)

If inter-process isolation similar to Linux is desired, where several tasks (threads) run in their own storage spaces (processes) and are completely isolated from each other, the chip hardware needs to add MMU modules, as well as privileged modes and software interrupts. The MMU module translates the virtual addresses accessed by threads into physical addresses before sending them to the bus.

At this point, the storage space where the RTOS kernel code resides is called kernel space, while the storage space for application task code and RTOS system service code is called user space. Each user process is allocated a user space, and one process protects one or more threads.

Linux (Based on MMU)

Embedded system application design based on Linux.

The layering is similar to the previous one, but the OS functionality is more complex. However, the Linux kernel is generally not referred to as RTOS because some of its functionalities (such as supporting memory virtualization (swap), complex driver systems, etc.) lead to poorer real-time performance.

BootLoader

In the above scenarios, if there are multiple possible locations for code storage or if online updates to program functionality are needed, a BootLoader software layer is often added, which executes only during startup/reboot.

Second Level Knowledge Points of Software

(3.5) Software Layer Structure;

Third Level Knowledge Points of Software Layer Structure

(3.5.1) Bare-Metal; (3.5.2) RTOS (I&II); (3.5.3) RTOS (III); (3.5.4) Linux;

Fourth Level Knowledge Points of RTOS (I&II)

(3.5.2.1) OpenHarmony LiteOS-M; (3.5.2.2) RT-Thread;

Fourth Level Knowledge Points of RTOS (III)

(3.5.3.1) RT-Thread Smart;

Third Level Knowledge Points of CPU/Core

(2.1.5) SysTick; (2.1.6) MPU; (2.1.7) Privileged Mode; (2.1.8) Software Interrupt; (2.1.9) MMU;

Note: The above content, except for the bare-metal architecture, most of the other parts belong to extended content, which is generally not detailed in microcomputer principle textbooks.

13. Cache

What is cache?

The internal structure of cache includes a cache controller and cache memory.

Cache memory is a type of memory, but its storage units do not correspond to fixed Memory Map addresses; instead, they are used to cache data from another set of slower memory.

The cache controller consists of digital circuits and memory, storing the relationship data between cache memory and corresponding addresses.

Cache is located between the CPU/Core and memory (RAM/Flash) bus, intercepting memory access requests from the CPU/Core. If the requested data is stored in the cache, it returns data from the cache memory (called a hit); if not, it sends a request to the cached memory to retrieve data from several address units surrounding its address, returning it to the CPU/Core and updating the cache memory content.

Why use cache?

Because the read/write speeds of memory with different implementation technologies vary greatly, which does not match the processing speed of the CPU/Core.

Using cache can reduce the latency when the CPU/Core reads instructions and writes/reads data.

When the response speed of memory is slower than the request signal speed of the CPU/Core, the bus connecting the CPU/Core to memory cannot use a synchronous bus but must change to a semi-synchronous bus, increasing response signals. When there is no response, the internal circuits of the CPU/Core need to wait, causing a stall.

When using cache, due to potential misses, the bus between the CPU/Core and cache needs to use a semi-synchronous bus.

The existence of cache is transparent to the CPU/Core.

Third Level Knowledge Points of Memory

(2.2.3) Cache;

14. Sleep/Power Management

The behavior of the CPU/Core:

(1) Continuously “fetches instructions, decodes instructions, executes instructions,” unless it encounters:

(2) A Reset signal, which restarts from a specific address;

(3) An interrupt, which pauses the execution of the current instruction stream, jumps to the interrupt service routine, and continues to “fetch instructions, decode instructions, execute instructions” until it encounters an interrupt return instruction to return to the breakpoint and continue execution;

(4) A pause instruction or sleep instruction, which pauses the behavior of “fetching instructions, decoding instructions, executing instructions,” waiting for a wake-up event to continue;

(5) …

Sleep is an important function of low-power embedded system chips, but it is generally not covered due to time constraints.

15. Debugging

The behavior of the CPU/Core:

(1) Continuously “fetches instructions, decodes instructions, executes instructions,” unless it encounters:

(2) A Reset signal, which restarts from a specific address;

(3) An interrupt, which pauses the execution of the current instruction stream, jumps to the interrupt service routine, and continues to “fetch instructions, decode instructions, execute instructions” until it encounters an interrupt return instruction to return to the breakpoint and continue execution;

(4) A pause instruction or sleep instruction, which pauses the behavior of “fetching instructions, decoding instructions, executing instructions,” waiting for a wake-up event to continue;

(5) A debugging module (debug) pauses or interrupts/encounters a breakpoint instruction, etc.;

(6) …

During experiments, debugging operations such as stepping through code, setting breakpoints, viewing registers, and viewing memory help understand and debug code, but the implementation of debugging functions is generally not introduced.

16. Summary

The starting point is the working process of the CPU/Core, “fetching instructions, decoding instructions, executing instructions.” This introduces instructions and instruction set architecture.

Where are instructions stored? This introduces memory. How to fetch? This introduces memory bus/system bus and Program Counter (PC).

How to decode instructions? This introduces reading instruction set architecture specifications, instruction formats, instruction classifications, and addressing modes.

Executing instructions, including arithmetic instructions, introduces Register File (RF) and ALU, relating to the four arithmetic operations, bitwise operations, and shift operations in C language; jump instructions relate to branching structures, loops, and function calls in C language; LOAD/STORE instructions introduce data memory and the storage of C language variables. Function calls introduce stacks and SP registers, LR registers.

Once calculations can be performed, how to interact with external circuits? This introduces peripherals. Control LEDs/buzzers through GPIO, read button states, implement hardware delays and PWM signal outputs through timers, and communicate with host computers/other modules through serial ports. How to control peripherals introduces I/O registers of peripherals, Memory Map, reading chip manuals, peripheral block diagrams, etc.

Using polling methods may not provide fast enough response, leading to the introduction of interrupts. Interrupts are a very important topic, associated with many terminologies.

The above covers the basic content.

From the perspective of improving processor chip performance:

The first intuitive method is to increase frequency. As the CPU/Core frequency increases, the working frequency of FLASH and SRAM cannot keep up, leading to the introduction of Cache. The bus between the Core and memory also changes from synchronous to semi-synchronous.

The CPU/Core wastes a lot of time on slow peripheral read/write data, leading to the introduction of DMA. This then causes bus contention, leading to the introduction of bus arbiters, bus matrices, etc.

The Core frequency cannot keep increasing indefinitely, leading to the introduction of pipelining, SIMD, VLIW, hardware threads, and other technologies.

Then there are multi-core/multi-processor systems.

Finally, the introduction of GPUs, accelerators, and co-processors.

From a software perspective, as code becomes increasingly complex, a single business logic cannot solve the problem:

Code is divided into multiple independent tasks (infinite loops), with dedicated code responsible for concurrent execution of multiple tasks, leading to the introduction of RTOS and threads.

Code is not written by a single person, and mutual distrust requires isolation of access (but still linked together). This leads to the introduction of MPU, requiring privileged modes and software interrupts.

Applications are not limited to one, and they are not written by a single unit, leading to mutual distrust and the need for isolation (completely unaware of each other’s existence), allowing for separate compilation and linking, independent installation and uninstallation. This leads to the introduction of MMU (requiring privileged modes and software interrupts).

There are many other extended options, which are not listed one by one.

Leave a Comment