当前位置: 首页 > news >正文

在新ARM板上移植U-Boot和Linux指南

序言

  • 从支持一个定制板子在U-Boot和Linux中的过程中得到经验
  • 以一个带有知名SoC(i.MX6)且IP已经得到支持的板子为例,这次讨论几乎不涉及编码技能,
  • 更多地聚焦在U-Boot部分

一般原则

  • 如果您有您的BSP(板级支持包)的源代码,请编译并运行BSP以:
    1. 验证您正在工作的IP(知识产权/硬件模块)能够与某些代码一起工作
    2. 拥有一个参考代码
    3. 拥有一个您可以用于调试的代码
  • 专注于正确配置RAM和UART
  • 提交
  • 一次处理一个IP
  • 提交

定制板介绍

  • 基于i.MX6的模块,带有扩展板,
  • 以太网,I2C,SPI,NAND,eMMC,SD卡读卡器,USB设备,EEPROM,
    GPIO,UART,音频(I2S),HDMI,LVDS,PCIe,USB主机,RTC,电源管理集成电路(PMIC)

U-Boot移植

U-Boot 状态

  • 持续从板头文件定义迁移到Kconfig选项,
  • 持续从手动驱动探测迁移到驱动模型

U-Boot 目录结构

  • arch/
    与架构或平台相关的所有内容:设备树(DTS)、CPU初始化、引脚复用控制器、DRAM、时钟等…
  • board/
    特定于板子的代码(初始化、引脚复用配置等),指定板头文件的Kconfig文件,板文件,路径,板文件的Makefile,
  • configs/
    所有板子的默认配置(defconfigs)
  • drivers/
  • include/
    所有头文件
  • include/configs/
    所有板子的头文件

U-Boot新板支持工作流程

  1. 创建板文件
  2. 创建板Kconfig文件
  3. 创建板Makefile
  4. 创建板defconfig
  5. 创建板头文件
  6. 在架构的Kconfig中包含板的Kconfig
  7. 在其CPU的Kconfig中定义TARGET Kconfig选项
    一些平台共享公共文件,因此只需要一个defconfig

创建板文件

board/my_vendor/my_board/my_board.c
在这里插入图片描述

  • 声明全局数据指针
  • 可以在代码中使用全局变量gd
  • 在ARM架构中,对于ARM32等于硬件寄存器r9,对于ARM64等于x18
  • 用于在启动后非常早期的“某些内存”中存储信息,这些内存在系统初始化期间可用(直到我们设置好内存控制器,可以使用RAM)
  • 查看include/asm-generic/global_data.h可以了解它能存储哪些类型的信息。

创建板Kconfig文件

board/my_vendor/my_board/Kconfig

在这里插入图片描述

  • SYS_VENDOR 和 SYS_BOARD 用于标识目录,这样 make 命令能找到编译所需的文件
    - 如果两者都存在
    board/SYS_VENDOR/SYS_BOARD/
    - 如果省略了 SYS_VENDOR
    board/SYS_BOARD/
    - 如果省略了 SYS_BOARD
    board/SYS_VENDOR/common/
  • SYS_CONFIG_NAME 用于标识板头文件
    include/configs/SYS_CONFIG_NAME.h

创建板Makefile文件

board/my_vendor/my_board/Makefile
在这里插入图片描述

创建板defconfig文件

configs/my_board_defconfig

在这里插入图片描述

  • 在这里放置任何可以在Kconfig(菜单配置)中选择的内容
  • 驱动程序、特性、U-Boot行为、库等

创建板header文件

include/configs/my_board.h
在这里插入图片描述

引入板子的Kconfig文件

arch/arm/Kconfig or
arch/arm/mach-imx/mx6/Kconfig
在这里插入图片描述

定义板子的TARGET Kconfig选项

arch/arm/mach-imx/mx6/Kconfig
在这里插入图片描述

U-Boot初始化序列

  • U-Boot会运行两组函数列表,其目的是在用户访问控制台之前初始化或配置特定的IP
  • 第一个列表定义在common/board_f.c文件中的static init_fnc_t init_sequence_f[]数组
  • 第一个列表负责初始化DRAM,映射它,并在工作后重新定位引导程序代码
  • 第二个列表定义在common/board_r.c文件中的static init_fnc_t init_sequence_r[]数组
  • 只有当定义了常量时,才会运行某些函数(例如,定义CONFIG_BOARD_EARLY_INIT_F以运行board_early_init_f())
  • 任何返回非零值的函数都会停止初始化序列,并使U-Boot无法启动
  • 在初始化序列有问题时定义DEBUG
  • 并非所有”特性”在所有函数中都可用(例如,board_early_init_f()中没有udelay)。

驱动选择

  • 从具有相同IP的板子中获取灵感
  • 检查相应子系统中的驱动程序
  1. 专注于驱动程序的行为
  2. 然后查看寄存器、位偏移、掩码等
  3. 检查未定义的宏或常量
  4. 查找被ifdef块包围的代码片段
    - 在子系统的Makefile中查找这个驱动程序的对象文件在这里插入图片描述
  • 使用grep搜索CONFIG_MY_DRIVER
    - 如果在某些Kconfig文件中是可见符号 => 添加到板子的defconfig中
    - 如果在某些Kconfig文件中是非可见符号或未定义 => 添加到板头文件中
  • 确保你的驱动程序被编译(查找my_driver.o)
  • 驱动程序文件位于drivers/mtd/nand/nand_mxs.c
  • 使用CONFIG_NAND_MXS来编译驱动程序
  • 使用CONFIG_SYS_MAX_NAND_DEVICE和CONFIG_SYS_NAND_BASE常量来配置设备

驱动选择 - NAND示例

configs/my_board_defconfig
在这里插入图片描述
include/configs/my_board.h
在这里插入图片描述
board/my_vendor/my_board.c
在这里插入图片描述

关于设备树的说明

  • 设备树的迁移始于2012年,代码正逐渐迁移,逐个驱动程序,逐个子系统
  • 驱动模型需要使用设备树
  • 大多数驱动程序有大量的CONFIG_DM条件编译块
    - 你不能真正基于每个驱动程序选择启用DM支持
  • 子系统核心代码也是如此
  • 我没有深入研究,因为我们要么不需要,要么需要完全支持设备树,而NAND框架还没有迁移到DM。

Linux Kernel 移植

Linux内核新板支持工作流程

1. 创建板子的设备树
2. 将板子的DTB添加到架构DTS Makefile中
3. 为你的板子创建一个默认配置(defconfig)

Device Tree

  • 一个特殊DTS(设备树源)格式的文件
  • 纯粹描述了你的板子的硬件
  • 通过兼容字符串将IP与驱动程序匹配
  • 文档可以在Documentation/devicetree/bindings中找到
  • 有关设备树是什么以及如何编写的更深入解释,请访问:设备树详细介绍视频。

创建板子的设备树

arch/arm/boot/dts/imx6s-my-board.dts
在这里插入图片描述

将DTB添加到架构DTS Makefile中

arch/arm/boot/dts/Makefile
在这里插入图片描述

为你的板子创建一个默认配置(defconfig)

  • 从SoC系列的defconfig开始(例如imx_v6_v7_defconfig),如果没有,从架构的defconfig开始(例如multi_v7_defconfig)
  • 从defconfig中删除无用的SoC系列、驱动程序和特性
  • 添加你想要编译的驱动程序的CONFIG
    - 使用grep搜索驱动程序的基本名称是正确的方法
    - 大多数驱动程序依赖于子系统或其他选项,如果你的驱动程序没有选择它们,你也需要将它们添加到你的defconfig中
  • PCIe驱动程序正在探测但未枚举设备
    - 驱动程序在BSP中工作,发现缺少对电源管理器的支持是罪魁祸首
    - 迅速编写了一个40行的补丁并提交给了上游
  • 以太网驱动程序缺少在BSP中设置的PHY复位后延迟
    - 迅速编写了一个20行的补丁并提交给了上游。

相关文章:

  • 空间计算/XR的现状:Meta Orion的优势与挑战
  • pgsql
  • 前端——js函数+DOM对象
  • 《 C++ 修炼全景指南:十三 》为什么你的代码不够快?全面掌控 unordered_set 和 unordered_map 的哈希性能飙升魔法
  • 基于Hive和Hadoop的白酒分析系统
  • 大模型微调方法(非常详细),收藏这一篇就够了!
  • 个人健康管理小程序(源码+参考文档+定制)
  • 【深度学习】05-RNN循环神经网络-02- RNN循环神经网络的发展历史与演化趋势/LSTM/GRU/Transformer
  • 数智算融合,大模型助力政务服务智能化转型 丨OPENAIGC开发者大赛企业组AI创作力奖
  • ansible 配置
  • VS code Jupyter notebook 导入文件目录问题
  • 实操了 AI 大模型项目落地, 程序员成功转变为 AI 大模型工程师
  • [大语言模型-论文精读] 词性对抗性攻击:文本到图像生成的实证研究
  • 基于51单片机的多通道数字电压表proteus仿真
  • map和set的使用
  • JavaScript-如何实现克隆(clone)函数
  • 【跃迁之路】【463天】刻意练习系列222(2018.05.14)
  • Angular 2 DI - IoC DI - 1
  • JS创建对象模式及其对象原型链探究(一):Object模式
  • maven工程打包jar以及java jar命令的classpath使用
  • Octave 入门
  • React16时代,该用什么姿势写 React ?
  • Redis 中的布隆过滤器
  • SegmentFault 2015 Top Rank
  • vue2.0项目引入element-ui
  • 关于springcloud Gateway中的限流
  • 后端_ThinkPHP5
  • 解析带emoji和链接的聊天系统消息
  • 如何使用 JavaScript 解析 URL
  • 视频flv转mp4最快的几种方法(就是不用格式工厂)
  • 学习JavaScript数据结构与算法 — 树
  • ​linux启动进程的方式
  • ​Z时代时尚SUV新宠:起亚赛图斯值不值得年轻人买?
  • #Java第九次作业--输入输出流和文件操作
  • (12)Linux 常见的三种进程状态
  • (14)学习笔记:动手深度学习(Pytorch神经网络基础)
  • (附源码)spring boot基于Java的电影院售票与管理系统毕业设计 011449
  • (附源码)springboot 校园学生兼职系统 毕业设计 742122
  • (附源码)计算机毕业设计SSM教师教学质量评价系统
  • (黑客游戏)HackTheGame1.21 过关攻略
  • (黑马C++)L06 重载与继承
  • (详细版)Vary: Scaling up the Vision Vocabulary for Large Vision-Language Models
  • (转)nsfocus-绿盟科技笔试题目
  • (转)创业的注意事项
  • (转)负载均衡,回话保持,cookie
  • (转载)Google Chrome调试JS
  • .htaccess配置常用技巧
  • .net core 外观者设计模式 实现,多种支付选择
  • .net websocket 获取http登录的用户_如何解密浏览器的登录密码?获取浏览器内用户信息?...
  • .NET 设计模式—适配器模式(Adapter Pattern)
  • .NET开源纪元:穿越封闭的迷雾,拥抱开放的星辰
  • .NET与java的MVC模式(2):struts2核心工作流程与原理
  • :中兴通讯为何成功
  • ?.的用法
  • @RestController注解的使用