Linux设备树[1]-解析设备树
Uboot如何将设备树传给kernel在riscv架构下,uboot会将dtb的物理地址放到a1寄存器中。 这点可在arch/riscv/head.S中看到些许端倪。 #ifdef CONFIG_BUILTIN_DTB la a0, __dtb_start XIP_FIXUP_OFFSET a0#else mv a0, a1#endif /* CONFIG_BUILTIN_DTB */ /* Set trap vector to spin forever to help debug */ la a3, .Lsecondary_park csrw CSR_TVEC, a3 call...
Uboot如何传递bootargs给Linux
Uboot如何传递bootargsuboot并不是直接将bootargs传递给kernel,而是修改dts中的chosen节点实现的。 在uboot中可以发现该函数: int fdt_chosen(void *fdt){ struct abuf buf = {}; int nodeoffset; int err; const char *str; /* used to set string properties */ ... /* find or create "/chosen" node. */ nodeoffset = fdt_find_or_add_subnode(fdt, 0, "chosen"); if (nodeoffset < 0) return nodeoffset; ... str = board_fdt_chosen_bootargs(fdt_get_property(fdt, nodeoffset, "bootargs",...
Linux设备树[0]-理解dtb格式
Linux设备树[0]-理解dtb格式 DTBdtb文件由dts通过dtc命令编译而来。 具体结构应该如下: alignment gap对齐中间的alignment gap部分表示对齐间隙,它并非是必须的,它是否被提供以及大小由具体的平台对数据对齐和的要求以及数据是否已经对齐来决定。 elf headerDTB文件跟elf文件一样,都有一个header,也就是meta-data。dtb文件的meta-data大小为40字节。 可以看下linux代码中对于dtb头信息的定义: // In scripts/dtc/libfdt/fdt.hstruct fdt_header { fdt32_t magic; /* magic word FDT_MAGIC */ fdt32_t totalsize; /* total size of DT block */ fdt32_t off_dt_struct; /* offset to structure */ fdt32_t off_dt_strings; /* offset to strings...
嵌入式Linux面经-随意随缘不完整版
🌐 一、内核基础(驱动和 BSP 的地基)Linux 内核启动流程?(从 U-Boot / ATF 到 init)系统上电后,SoC 会从固化的启动介质(如 SPI NOR/NAND)加载第一阶段 Bootloader,通常是 SPL(Secondary Program Loader),接着加载第二阶段的 U-Boot。 在 U-Boot 中主要做这些事: 初始化 DRAM,准备运行内核的内存环境 初始化串口、网络、存储等基本外设(可选) 读取设备树(.dtb)、kernel 镜像(zImage/Image)、initrd 最后调用 bootm 或 booti 命令,引导内核 可选阶段:ATF(Arm Trusted Firmware)或 OpenSBI(RISC-V)如果是 RISC-V 架构,这一步通常由 OpenSBI 负责: 设置机器模式下的一些 CSR、trap handler 创建 S-mode 的运行环境(包括 timer 中断、console、PMP) 提供 SBI 接口(给 S-mode 的 Linux...
platform device driver[1]
platform device driver[0]platform device driver[1] Platform驱动probe函数是如何被调用的回到我们最常使用的platform_driver_register函数,这其实是一个宏定义,属于函数wrap。 /* * use a macro to avoid include chaining to get THIS_MODULE */#define platform_driver_register(drv) \ __platform_driver_register(drv, THIS_MODULE) __platform_driver_register__platform_driver_register函数定义如下: /** * __platform_driver_register - register a driver for platform-level devices * @drv: platform driver structure * @owner: owning module/driver */int...
platform device driver[0]
platform device driver[0]platform device driver[1] Platform 在Linux设备驱动模型中 (since v2.6),需要关心总线,设备和驱动这三个实体。总线将设备与驱动绑定。在设备注册或者注册驱动的时候,总线都会寻找与其相对应的驱动或设备进行匹配。 一个现实的Linux 设备和驱动通凋阁需要挂接在一种总线上,对于本身依附于 PCI.USB,I2C、SPI等的设备而言,自然不是问题但是在嵌人式系统里面,在 Soc 系统中华集成的独立外设控制器、挂接在 Soc 内存空间的外设等却不依附于此类总线。基于这一背景,Linux 发明了一种虚拟的总线,称为platform 总线,相应的设备称为platform_device,而驱动成为platform _driver。 所谓的platform_device并不是与字符设备、块设备和网络设备并列的概念。比如lcd, i2c,...
elf文件[0]-section和segment的区别
系列: elf文件[0]-section和segment的区别 Section 是给链接器和调试器看的,Segment 是给程序加载器(比如内核、bootloader)加载用的。 具体区别 对比项 Section(段) Segment(程序段) 来自哪儿 Section Header Table(由 shoff 定位) Program Header Table(由 phoff 定位) 用途 给 链接器、调试器 用 给 加载器(如 exec) 用 是否加载进内存 不一定,比如 .symtab、.strtab 等只调试用 是的,PT_LOAD 类型会加载进内存 典型内容 .text, .data, .bss, .rodata 等 一个 Segment 可能包含多个 Section 是否可选 可选(strip 可移除) 必须存在,运行离不开它 ELF 文件结构中 在 Section Header Table 描述 在 Program Header Table...
linux i2c驱动框架分析[1]
系列: linux i2c驱动框架分析[0]linux i2c驱动框架分析[1] I2C设备驱动程序框架IIC设备驱动是对IIC硬件体系结构中设备端的实现,设备一般挂接在受CPU控制的IIC适配器上,通过IIC适配器与CPU交换数据。设备驱动则是与挂在I2C总线上的具体的设备通讯的驱动。通过I2C总线驱动提供的函数,设备驱动可以忽略不同总线控制器的差异,不考虑其实现细节地与硬件设备通讯。 IIC设备驱动主要包含了数据结构i2c_driver和i2c_client,我们需要根据具体设备实现其中的成员函数。 其中,i2c_client由dts自动生成,如果设备在设备树中有 i2c@xxx 和 your_device@address 的节点,内核会根据设备树生成 i2c_client 实例,然后和匹配的 i2c_driver 执行绑定。 接口i2c_driver首先看下最关键的结构体,这是我们用来和Linux交互的关键核心。 struct i2c_driver { unsigned int class; /* Standard driver model...
linux i2c驱动框架分析[0]
系列: linux i2c驱动框架分析[0]linux...
linux的initcall机制
什么是initcallinitcall 是Linux 内核中的一种机制,用于在系统启动过程中自动执行初始化函数。这些函数在内核启动阶段被内核自动调用,用于初始化各种子系统、总线、驱动、文件系统等。 也就是说,如果我们的驱动想要被linux调用,就要使用initcall来“通知”linux: 我需要被你调用。 在驱动中我们可以看到xxx_init这样的形式,比如module_init initcall的种类在linux6.15.0-rc1的include/linux/init.h中可以看到如下代码: #ifdef CONFIG_HAVE_ARCH_PREL32_RELOCATIONS#define ____define_initcall(fn, __stub, __name, __sec) \ __define_initcall_stub(__stub, fn) \ asm(".section \"" __sec "\", \"a\" \n" \ __stringify(__name)...