debug
[TOC] arch/arm/include/debug/stm32.Saddruart 添加debug串口地址1234.macro addruart, rp, rv, tmp ldr \rp, =CONFIG_DEBUG_UART_PHYS @ physical base ldr \rv, =CONFIG_DEBUG_UART_VIRT @ virt base.endm CONFIG_DEBUG_UART_PHYS 和 CONFIG_DEBUG_UART_VIRT1234567891011121314151617//arch/arm/Kconfig.debugconfig DEBUG_UART_VIRT default DEBUG_UART_PHYS if !MMUconfig DEBUG_UART_PHYS default 0x40011000 if STM32F4_DEBUG_UART || STM32F7_DEBUG_UART || \ STM32H7_DEBUG_UARTconfig STM32H7_DEBUG_UART b...
include
[TOC] arch/arm/include/asm/cache.h__read_mostly 大多数读取 __read_mostly用于标记大多数读取的变量,在编译时会将该变量放到.data..read_mostly段中 1#define __read_mostly __section(".data..read_mostly") __read_mostly的作用是将变量放到.data..read_mostly段中,该段在内核启动时会被清零,所以该变量在内核启动时会被清零 arch/arm/include/asm/cmpxchg.harch_xchg_relaxed __arch_xchg 交换数据的逻辑都一样 使用ldrexb加载数据,它还会设置一个标志,表示该地址被标记为“独占访问”,以便后续的存储操作可以检查是否有其他处理器访问了该地址。 使用strexb存储数据,如果成功,返回0;如果失败,返回1,并且会清除“独占访问”标志。 如果strexb失败,循环会重新尝试加载...
boot
[TOC] arch/arm/boot: Linux 32位ARM架构的启动基石arch/arm/boot 目录是 Linux 内核源码中专门为 32 位 ARM 架构(AArch32)设计的启动代码所在地。它的核心使命是充当引导加载程序(Bootloader,如 U-Boot)与体系结构无关的通用内核代码之间的桥梁。这个目录下的代码负责处理内核启动最初始、最底层的阶段,为 C 语言环境的建立和主内核的执行做好万全准备。 一、 核心职责arch/arm/boot 目录下的代码和构建脚本共同完成了以下几项至关重要的任务: 生成可启动的内核镜像: 该目录下的 Makefile 是构建过程的核心,它负责将编译好的内核 vmlinux(一个 ELF 格式的文件)进行处理,最终生成 Bootloader 可以直接加载和执行的镜像格式,最常见的有 zImage 和 uImage。 内核解压缩: 为了减小存储体积和加快加载速度,内核镜像通常是经过压缩的。arch/arm/boot 包含了一个微型的、自解压的前端程序(Decompressor)。当 Bootloader...
lds
[TOC] arch/arm/Makefile: 32位ARM架构的构建总指挥arch/arm/Makefile 是 Linux 内核 Kbuild 系统中专门为 32 位 ARM 架构服务的顶级 Makefile。它不是一个独立的可执行脚本,而是被主 Makefile 包含(include)进去的。它的核心职责是定义 ARM 架构独有的构建规则、配置编译选项,并将 Kconfig 中选择的平台配置转化为实际的构建命令。 可以将其视为一个“总指挥官”,它接收来自 .config 文件的战略指令,然后向编译器、链接器等“部队”下达精确的战术命令,以确保最终能为特定的 ARM 平台构建出正确、高效的内核。 一、 核心角色与职责 定制化主构建流程: 内核的主 Makefile 定义了通用的构建目标(如 vmlinux, modules)。arch/arm/Makefile 则对这些目标进行“重载”或“定制”,添加 ARM 架构特有的依赖和命令。 配置翻译官: 将 .config 文件中由 Kconfig 系统生成的高层配置选项(例如 CONFIG_ARCH_BC...
assembly
[TOC] THUMB2指令集THUMB2 指令集深度解析:从入门到精通THUMB2 指令集是在嵌入式系统领域广受欢迎的 ARM 架构的一项关键技术。它巧妙地结合了 16 位指令的紧凑代码密度和 32 位指令的强大性能,为资源受限的设备提供了高效的解决方案。本文将从历史背景、核心原理、应用场景、入门实践、安全考量、生态系统、性能监控和未来趋势等多个维度,为您全面解析 THUMB2 指令集。 一、 历史与背景为了解决什么特定问题而诞生? THUMB2 技术的诞生主要是为了解决早期 ARM 架构在嵌入式应用中的一个核心矛盾:性能与代码密度之间的权衡。 ARM 指令集:提供强大的 32 位指令,性能出色,但指令均为 32 位定长,导致代码体积较大,对于内存(尤其是昂贵的片上闪存和 RAM)有限的嵌入式系统而言,成本较高。 Thumb 指令集(第一代):作为对策,ARM 推出了 16 位的 Thumb 指令集,它是 ARM 指令集的一个子集。 这显著减小了代码体积(约 30%-40%),降低了功耗和内存需求。 然而,Thumb 指令集功能有限,性能相比 32 位 ARM 指令集有所下降...
lib
[TOC] arch/arm/include/asm/delay.h该文件的核心原理是提供一个可插拔的、分层的延迟实现机制。它设计了一个抽象的arm_delay_ops操作函数集, 允许在系统启动时根据可用的硬件资源来选择并注册最优的延迟方法。 对于没有精确硬件定时器的旧系统: 它会回退到一种基于”每秒循环数”(loops_per_jiffy)的校准循环方法。内核在启动时会测量在一个系统时钟节拍(jiffy)内, CPU能执行多少次空循环, 从而计算出一个近似值。udelay的实现会根据这个校准值来计算需要执行多少次循环才能达到指定的微秒延迟。 对于拥有高精度硬件定时器的新系统(如STM32H750): 系统启动代码(通常是特定于板卡的平台代码)可以使用register_current_timer_delay函数来注册一个高精度的定时器(例如ARM Cortex-M内核自带的DWT周期计数器CYCCNT)。一旦注册成功, arm_delay_ops中的函数指针就会被更新为指向基于这个硬件定时器的延迟实现。这种实现方式会读取当前定时器计数值...
mm
[TOC] arch/arm/mm: 解剖Linux的NOMMU内存模型arch/arm/mm 目录包含了 ARM 架构的内存管理代码。在典型的带 MMU 的系统中,它的主要职责是处理虚拟内存、页表、TLB 管理等。但是,当内核被配置为在没有 MMU 的处理器(如 ARM Cortex-M 系列)上运行时,这个目录的功能会发生根本性的变化。 在 NOMMU 模式下,arch/arm/mm 的核心任务不再是管理复杂的虚拟地址空间,而是直接管理一个扁平的、统一的物理地址空间。 一、 NOMMU 的核心概念在深入代码之前,必须理解 NOMMU 环境下的几个基本事实: 单一扁平地址空间: 内核、所有用户进程、I/O 内存都共享同一个物理地址空间。不存在虚拟地址到物理地址的转换。一个指针的值就是它在物理内存中的真实地址。 无内存保护: 由于没有 MMU,处理器无法在硬件层面阻止一个进程访问另一个进程或内核的内存。任何一个有缺陷的应用程序都可以直接读写内核内存,导致整个系统崩溃。 受限的进程模型: 传统的 fork() 系统调用(它依赖于写时复制技术,而这又...
process
[TOC] processarch/arm/include/asm/current.h 返回__current的值,__current是一个全局变量,在arch/arm/kernel/process.c中定义 __current是一个指向当前进程的指针,在内核中,每个进程都有一个task_struct结构体,该结构体包含了该进程的所有信息 12345678910111213141516171819202122//arch/arm/kernel/process.casmlinkage struct task_struct *__current;EXPORT_SYMBOL(__current);static __always_inline __attribute_const__ struct task_struct *get_current(void){ struct task_struct *cur;#if __has_builtin(__builtin_thread_pointer) && defined(CON...
base
[TOC] drivers/basedrivers/base 是Linux内核源代码中的一个核心目录,它并非一项独立的技术,而是内核设备模型(Linux Device Model)的基础实现。这个模型是一个统一的、抽象的框架,用于管理系统中的所有设备、驱动程序以及它们之间的关系。理解drivers/base就是理解现代Linux内核如何看待和管理硬件。 历史与背景这项技术是为了解决什么特定问题而诞生的? 在Linux内核2.5版本之前,内核中没有一个统一的结构来表示设备和驱动程序。驱动程序的编写和管理方式较为混乱,存在诸多问题: 电源管理困难:没有统一的设备层级结构,很难以正确的顺序对设备进行挂起(suspend)或恢复(resume)操作。例如,USB主控制器必须在USB设备之前被挂起。 代码冗余:每个子系统(如PCI, USB)都需要自己实现一套管理设备和驱动的机制,导致了大量的重复代码,尤其是在对象生命周期管理(如引用计数)和列表管理方面。 系统信息不透明:缺乏一种简洁、一致的方式从用户空间查看系统中所有设备的拓扑结构和状态。当时的 /proc 文件系统虽...
sys_call_table
Linux内核ARM架构下sys_call_table的自动化生成机制剖析1. 引言在Linux操作系统内核中,系统调用(System Call)构成了用户空间与内核空间交互的基础接口。为了高效地将用户空间传递的系统调用号(System Call Number, SCN)映射至内核中相应的服务例程,内核在内部维护了一个核心数据结构——系统调用表。对于ARM架构,此表定义为sys_call_table,其本质是一个函数指针数组。 维护这样一个包含数百个条目,且需兼容多种应用程序二进制接口(Application Binary Interface, ABI)的数组,是一项复杂且易错的任务。任何手动的编辑都可能引入调用号与函数指针不匹配、ABI兼容性层实现错误或表大小同步失败等严重问题。为规避此类风险,Linux内核采用了一套高度自动化的代码生成机制。本文旨在以严谨的技术视角,对ARM架构下sys_call_table从源定义文件到最终二进制镜像中符号的全过程,进行深入、详尽的剖析。 2. sys_call_table 自动化生成流程sys_call_table的构建并非在C代码层面进...







