ARM uboot 源码分析7 - uboot的命令体系

news2024/10/2 22:23:17

一、uboot 命令体系基础

1、使用 uboot 命令

(1) uboot 启动后进入命令行环境下,在此输入命令按回车结束,uboot 会收取这个命令然后解析,然后执行。


2、uboot 命令体系实现代码在哪里

(1) uboot 命令体系的实现代码在 uboot/common/cmd_xxx.c 中。有若干个 .c 文件和命令体系有关。(还有 command.c main.c 也是和命令有关的)

在这里插入图片描述


3、每个命令对应一个函数

(1) 每一个 uboot 的命令背后都对应一个函数。这就是 uboot 实现命令体系的一种思路和方法。

(2) 我们要找到每一个命令背后所对应的那个函数,而且要分析这个函数和这个命令是怎样对应起来的。


4、命令参数以 argc & argv 传给函数

(1) 有些 uboot 的命令还支持传递参数。也就是说命令背后对应的函数接收的参数列表中有 argc 和 argv,然后命令体系会把我们执行命令时的命令+参数(md 30000000 10)以 argc(3)和 argv(argv[0]=md, argv[1]=30000000 argv[2]=10)的方式传递给执行命令的函数。

举例分析,以 help 命令为例:
help 命令背后对应的函数名叫:do_help。在 uboot/common/command.c 的236行。int do_help (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])

在这里插入图片描述


二、uboot 命令解析和执行过程分析

1、从 main_loop 说起

(1) uboot 启动的第二阶段,在初始化了所有该初始化的东西后,进入了一个死循环,死循环的循环体就是 main_loop。

(2) main_loop 函数执行一遍,就是一个获取命令、解析命令、执行命令的过程。

(3) run_command 函数就是用来执行命令的函数。

在这里插入图片描述


2、run_command 函数关键点分析

(1) 控制台命令获取;

(2) 命令解析。parse_line 函数把 “md 30000000 10” 解析成 argv[0]=md, argv[1]=30000000 argv[2]=10;

在这里插入图片描述


(3) 在命令集中去查找命令。find_cmd(argv[0]) 函数去 uboot 的命令集合当中搜索有没有 argv[0] 这个命令。
在这里插入图片描述


(4) 执行命令。最后用函数指针的方式调用执行了对应函数。

在这里插入图片描述

思考:关键点就在于 find_cmd 函数如何查找到这个命令是不是 uboot 的合法支持的命令?这取决于 uboot 的命令体系机制(uboot 是如何完成命令的这一套设计的,命令如何去注册、存储、管理、索引。)。


三、uboot如何处理命令集1

1、可能的管理方式

(1) 数组。结构体数组,数组中每一个结构体成员就是一个命令的所有信息。

(2) 链表。链表的每个节点 data 段就是一个命令结构体,所有的命令都放在一条链表上。这样就解决了数组方式的不灵活。坏处是需要额外的内存开销,然后各种算法(遍历、插入、删除等)需要一定复杂度的代码执行。

(3) 有第三种吗?uboot 没有使用数组或者链表,而是使用了一种新的方式来实现这个功能。


2、命令结构体 cmd_tbl_t

在这里插入图片描述
在这里插入图片描述

(1) name:命令名称,字符串格式。

(2) maxargs:命令最多可以接收多少个参数。

(3) repeatable:指示这个命令是否可重复执行。重复执行是 uboot 命令行的一种工作机制,就是直接按回车则执行上一条执行的命令。

(4) cmd:函数指针,命令对应的函数的函数指针,将来执行这个命令的函数时,使用这个函数指针来调用。

(5) usage:命令的短帮助信息。对命令的简单描述。

(6) help:命令的长帮助信息。细节的帮助信息。

(7) complete:函数指针,指向这个命令的自动补全的函数。


总结:uboot 的命令体系在工作时,一个命令对应一个 cmd_tbl_t 结构体的一个实例,然后 uboot 支持多少个命令,就需要多少个结构体实例。uboot 的命令体系把这些结构体实例管理起来,当用户输入了一个命令时,uboot 会去这些结构体实例中查找(查找方法和存储管理的方法有关)。如果找到则执行命令,如果未找到则提示命令未知。


3、uboot 实现命令管理的思路

在这里插入图片描述

在这里插入图片描述

(1) 填充 1 个结构体实例构成一个命令

(2) 给命令结构体实例附加特定段属性(用户自定义段),链接时将带有该段属性的内容链接在一起排列(挨着的,不会夹杂其他东西,也不会丢掉一个带有这种段属性的,但是顺序是乱序的)。

(3) uboot 重定位时,将该段整体加载到 DDR 中。加载到 DDR 中的 uboot 镜像中,带有特定段属性的这一段,其实就是命令结构体的集合,有点像一个命令结构体数组。

(4) 段起始地址和结束地址(链接地址、定义在 u-boot.lds 中)决定了这些命令集的开始和结束地址。

在这里插入图片描述

在这里插入图片描述


四、uboot 如何处理命令集2

1、uboot 命令定义具体实现分析

(1) U_BOOT_CMD 宏基本分析

在这里插入图片描述

这个宏定义在 uboot/include/command.h 中。

U_BOOT_CMD(
version, 1, 1, do_version,
“version - print monitor version\n”,
NULL
);

这个宏替换后变成:

cmd_tbl_t __u_boot_cmd_version attribute ((unused,section (“.u_boot_cmd”))) = {#name, maxargs, rep, cmd, usage, help}

在这里插入图片描述

总结:这个 U_BOOT_CMD 宏的理解,关键在于结构体变量的名字和段属性。名字使用 ## 作为连字符,附加了用户自定义段属性,以保证链接时将这些数据结构链接在一起排布。

(2) 链接脚本。


2、find_cmd 函数详解

在这里插入图片描述

(1) find_cmd 函数的任务,是从当前 uboot 的命令集中查找是否有某个命令。如果找到则返回这个命令结构体的指针,如果未找到返回 NULL。

(2) 函数的实现思路很简单,如果不考虑命令带点的情况(md.b md.w 这种)就更简单了。查找命令的思路其实就是 for 循环遍历数组的思路,不同的是数组的起始地址和结束地址是用地址值来给定的,数组中的元素个数是结构体变量类型。

在这里插入图片描述


3、U_BOOT_CMD 宏详解

(1) 这个宏其实就是定义了一个命令对应的结构体变量,这个变量名和宏的第一个参数有关;因此只要宏调用时,传参的第一个参数不同,则定义的结构体变量不会重名。


4、命令举例:version 命令

在这里插入图片描述


五、uboot 中增加自定义命令

1、在已有的 c 文件中直接添加命令

(1) 在uboot/common/command.c中添加一个命令,叫:mycmd。

(2) 在已有的.c文件中添加命令比较简单,直接使用U_BOOT_CMD宏即可添加命令,给命令提供一个do_xxx的对应的函数这个命令就齐活了。

(3) 添加完成后要重新编译工程(make distclean; make x210_sd_config; make),然后烧录新的uboot去运行即可体验新命令。

(4)还可以在函数中使用argc和argv来验证传参。


2、自建一个 c 文件并添加命令

(1) 在uboot/common目录下新建一个命令文件,叫cmd_aston.c(对应的命令名就叫aston,对应的函数就叫do_aston函数),然后在c文件中添加命令对应的U_BOOT_CMD宏和函数。注意头文件包含不要漏掉。

(2) 在uboot/common/Makefile中添加上aston.o,目的是让Make在编译时能否把cmd_aston.c编译链接进去。

(3) 重新编译烧录。重新编译步骤是:make distclean; make x210_sd_config; make


3、体会:uboot 命令体系的优点

(1) uboot的命令体系本身稍微复杂,但是他写好之后就不用动了。我们后面在移植uboot时也不会去动uboot的命令体系。我们最多就是向uboot中去添加命令,就像本节课所做的这样。

(2) 向uboot中添加命令非常简单。


源自朱友鹏老师.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/369687.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

PA的包络跟踪电源

对于传统PA,电源一般设计成固定电压供电,电压不可变化。这种设计对于GSM和GPRS等使用恒定包络GMSK调制的系统来说,PA的效率是比较高的。 ​但随着追求更高的数据吞吐量以及更高的频谱效率,在现代的通信系统中使用了更复杂的调制方…

react定义css样式,使用less,css模块化

引入外部 css文件 import ./index.css此时引入的样式是全局样式 使用less 安装 npm i style-loader css-loader sass-loader node-sass -D生成config文件夹 npm run eject配置 以上代码运行完,会在根目录生成config文件夹 进入 config > webpack.config.js 查找…

基于jeecgboot的flowable为uniapp适配的流程页面调整

为了满足在uniapp上也能进行webview的流程页面操作与显示&#xff0c;需要对流程页面&#xff0c;特别是record/index.vue进行修改与适配。 一、对各个内容的宽带进行调整 主要是样式的调整 <el-col :span"16" :offset"4" 都修改成<el-col :span…

倾向得分匹配只看这篇就够了

一、倾向得分匹配法说明 倾向得分匹配模型是由Rosenbaum和Rubin在1983年提出的&#xff0c;首次运用在生物医药领域&#xff0c;后来被广泛运用在药物治疗、计量研究、政策实施评价等领域。倾向得分匹配模型主要用来解决非处理因素&#xff08;干扰因素&#xff09;的偏差。 …

协作对象死锁及其解决方案

协作对象死锁及其解决方案 1.前言 在遇到转账等的需要保证线程安全的情况时&#xff0c;我们通常会使用加锁的方式来保证线程安全&#xff0c;但如果无法合理的使用锁&#xff0c;很可能导致死锁。或者有时我们使用线程池来进行资源的使用&#xff0c;如调用数据库&#xff0…

Swagger狂神学习笔记

学习目标&#xff1a; 了解Swagger的概念及作用 掌握在项目中集成Swagger自动生成API文档 前后端分离 前端 -> 前端控制层、视图层 后端 -> 后端控制层、服务层、数据访问层 前后端通过API进行交互 前后端相对独立且松耦合 产生的问题 前后端集成&#xff0c;前端或…

支持U盘数据、误删文件、硬盘数据 、回收站数据恢复的软件

好用的Windows数据恢复软件的标准 在数字和信息经济时代&#xff0c;数据是必不可少的。没有人可以承受由于意外删除、格式化和其他原因导致数据丢失的风险。与其在数据恢复服务上花费大量资金或花费大量时间努力自己取回数据&#xff0c;用户更喜欢使用Windows数据恢复软件…

Ask林曦|来回答,30个你关心的日常问题(一)

在林曦老师的线上书法直播课上&#xff0c;上课前后的聊天时间里&#xff0c;时常有同学向林曦老师提问&#xff0c;这些问题涵盖了日常生活的诸多方面&#xff0c;从身体的保养&#xff0c;到快乐的法门&#xff0c;皆是大家感兴趣的&#xff0c;也都共同关切的。      暄…

破解票房之谜:为何高票房电影绕不过“猫眼们”?

如此火爆的春节档很多&#xff0c;如此毁誉参半的春节档鲜有。2023开年&#xff0c;集齐张艺谋、沈腾的《满江红》&#xff0c;以及有票房前作打底的《流浪地球2》接连两部春节档电影票房进入前十&#xff0c;为有些颓靡的中国电影市场注入了一针“强心剂”。与票房同样热闹起来…

git实战技巧-本地刚做出的修改、暂存和提交如何进行撤销

1、解决思路工作区和暂存区内容的撤销&#xff0c;直接按照对应命令或者IDEA界面完成操作就行。对于已提交的撤销回滚建议如下&#xff1a;1. 代码如果仅仅是回撤到指定版本&#xff0c;该版本之上的更新是不需要的&#xff0c;选择Hard模式。2. 代码回撤到指定版本时&#xff…

父传子与子传父步骤

父传子&#xff1a; 问题&#xff1a;父页面中引入子组件 把想要传给子页面的值用在子组件中用 &#xff1a;值“值” (用同一个值好区分)来绑定。 在子页面中用props接收 子组件不能改变父组件传过来的值。&#xff08;传多个页面的时候是&#xff0c;比如父传孙的时候我会…

2020蓝桥杯真题门牌制作(填空题) C语言/C++

题目描述 本题为填空题&#xff0c;只需要算出结果后&#xff0c;在代码中使用输出语句将所填结果输出即可。 小蓝要为一条街的住户制作门牌号。 这条街一共有 2020 位住户&#xff0c;门牌号从 1 到2020 编号。 小蓝制作门牌的方法是先制作 0 到 9 这几个数字字符&#xff…

两款全新模式——代言人、合伙人的玩法分享

近几年来&#xff0c;伴随着技术创新与时代发展趋势&#xff0c;线上消费订单配送服务高效率变得更加高&#xff0c;生活节奏的加快也使人们对于消费及时性越来越注重&#xff0c;及时要求已经大爆发。 用户的消费方式也发生了翻天覆地的变化&#xff0c;消费者跟商家不再是单…

jvm常识

Jvm工作原理学习笔记0126一、JVM的生命周期1.JVM实例对应了一个独立运行的java程序它是进程级别a)启动。启动一个Java程序时&#xff0c;一个JVM实例就产生了&#xff0c;任何一个拥有public static void main(String[] args)函数的class都可以作为JVM实例运行的起点b)运行。ma…

Revit中如何使管道垂直连接及【支管升降】

一、Revit中如何使管道垂直连接 在管道的标高与所要相连的管子相差无几的时候&#xff0c;拉动管道所产生的管道连接方式往往不符合应有的设计思路&#xff0c;如图1所示&#xff1a; 1)相连之后所生成的一个布线方案&#xff0c;但不是我们所想要的布线方案。如图2所示&#x…

PPP点到点协议认证之PAP认证

PPP点到点协议认证之PAP认证 需求 如图配置接口的IP地址将R1配置为认证端&#xff0c;用户名和密码是 huawei/hcie &#xff0c;使用的认证方式是pap确保R1和R2之间可以互相ping通 拓扑图 配置思路 确保接口使用协议是PPP确保接口的IP地址配置正确在R1 的端口上&#xff0c…

【LeetCode】剑指 Offer 14- I. 剪绳子 p96 -- Java Version

题目链接&#xff1a;https://leetcode.cn/problems/jian-sheng-zi-lcof/ 1. 题目介绍&#xff08;14- I. 剪绳子&#xff09; 给你一根长度为 n 的绳子&#xff0c;请把绳子剪成整数长度的 m 段&#xff08;m、n都是整数&#xff0c;n>1并且m>1&#xff09;&#xff0c…

【Mysql】InnoDB引擎

【Mysql】InnoDB引擎 文章目录【Mysql】InnoDB引擎1. 逻辑存储结构2. 架构2.1 概述2.2 内存结构2.2.1 Buffer Pool(缓冲池)2.2.2 Change Buffer(更改缓冲区)2.2.3 Adptive Hash Index(自适应hash索引)2.2.4 Log Buffer(日志缓冲区)2.3 磁盘结构2.3.1 System Tablespace(系统表空…

图解LeetCode——剑指 Offer 42. 连续子数组的最大和

一、题目 输入一个整型数组&#xff0c;数组中的一个或连续多个整数组成一个子数组。求所有子数组的和的最大值。要求时间复杂度为O(n)。 二、示例 2.1> 示例1: 【输入】 nums [-2,1,-3,4,-1,2,1,-5,4] 【输出】 6 【解释】 连续子数组 [4,-1,2,1] 的和最大&#xff0c;…

鉴源论坛 · 观擎丨民机机载软件中的开发和验证工具

作者 |蔡喁 上海控安可信软件创新研究院副院长 版块 | 鉴源论坛 观擎 01 工具鉴定 现代软件工程中&#xff0c;工具已经出现在软件研制过程中的各个环节中。在常见的软件研制环节中&#xff0c;使用工具包括软件需求工具、软件设计工具、软件架构工具和软件测试工具等。这…