内核移植——开发板的软件抽象(struct machine_desc)

以下内容源于朱有鹏嵌入式课程的学习与整理,如有侵权请告知删除。

内核支持什么架构、支持哪款cpu,这是如何确定的?主要是通过机器码来确定的。

内核中定义了一份机器码,uboot也会给内核传递一个机器码。

在内核启动的汇编阶段,head.S文件对比uboot传给内核的机器码和内核定义的机器码,如果匹配则继续启动。

本文主要讲内核如何定义机器码的(以下内容说的是三星待移植版本内核)。

1、struct machine_desc 结构体

这个结构体定义在/arch/arm/include/asm/mach/arch.h文件中,它的内容如下:

struct machine_desc {
	/*
	 * Note! The first four elements are used
	 * by assembler code in head.S, head-common.S
	 */
	unsigned int		nr;		/* architecture number	*/
	unsigned int		phys_io;	/* start of physical io	*/
	unsigned int		io_pg_offst;	/* byte offset for io 
						 * page tabe entry	*/

	const char		*name;		/* architecture name	*/
	unsigned long		boot_params;	/* tagged list		*/

	unsigned int		video_start;	/* start of video RAM	*/
	unsigned int		video_end;	/* end of video RAM	*/

	unsigned int		reserve_lp0 :1;	/* never has lp0	*/
	unsigned int		reserve_lp1 :1;	/* never has lp1	*/
	unsigned int		reserve_lp2 :1;	/* never has lp2	*/
	unsigned int		soft_reboot :1;	/* soft reboot		*/
	void			(*fixup)(struct machine_desc *,
					 struct tag *, char **,
					 struct meminfo *);
	void			(*map_io)(void);/* IO mapping function	*/
	void			(*init_irq)(void);
	struct sys_timer	*timer;		/* system tick timer	*/
	void			(*init_machine)(void);
};

这个结构体的一个实例,就是一块开发板的软件抽象。

2、mach-xxx/mach-yyy.c文件

在内核源码/arch/arm/目录中有许多mach-xxx目录(不同的xxx表示不同的CPU),这些mach-xxx目录中又有许多mach-yyy.c文件(表示采用相同CPU的不同开发板,而且开发板名字就叫yyy)。

分析发现,每个mach-yyy.c文件中,都通过MACHINE_START宏,定义了一个表征某个开发板的struct machine_desc类型的变量。而且这些结构体变量都被放到.arch.info.init段,表示当前内核可以支持这些机器码对应的开发板。

2.1 宏 MACHINE_START 的简介

这个宏定义在/arch/arm/include/asm/mach/arch.h文件中,它的内容如下:

/*
 * Set of macros to define architecture features.  This is built into
 * a table by the linker.
 */
#define MACHINE_START(_type,_name)			\
static const struct machine_desc __mach_desc_##_type	\
 __used							\
 __attribute__((__section__(".arch.info.init"))) = {	\
	.nr		= MACH_TYPE_##_type,		\
	.name		= _name,

#define MACHINE_END				\
};

这个宏用来定义一个数据类型为 struct machine_desc 的变量(实际上只定义了结构体前面部分的内容),而且这个变量会被定义到一个特定段.arch.info.init,因此这个变量将来会被链接器链接到这个.arch.info.init段中。

2.1.1 举例说明 

比如在/arch/arm/mach-s5pv210/mach-smdkv210.c文件中,有代码如下:

MACHINE_START(SMDKV210, "SMDKV210")
	/* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
	.phys_io	= S3C_PA_UART & 0xfff00000,
	.io_pg_offst	= (((u32)S3C_VA_UART) >> 18) & 0xfffc,
	.boot_params	= S5P_PA_SDRAM + 0x100,
	.init_irq	= s5pv210_init_irq,
	.map_io		= smdkv210_map_io,
	.init_machine	= smdkv210_machine_init,
#ifdef CONFIG_S5P_HIGH_RES_TIMERS
	.timer		= &s5p_systimer,
#else
	.timer		= &s3c24xx_timer,
#endif
MACHINE_END

这段代码其实等价于下面这段代码:

static const struct machine_desc __mach_desc_SMDKV210	\
 __used							\
 __attribute__((__section__(".arch.info.init"))) = {	\
	.nr		        = MACH_TYPE_SMDKV210,\//机器码2456		
	.name		    = "SMDKV210",
//MACHINE_START(SMDKV210, "SMDKV210")展开后是上面这部分(没有“}”这个符号)

    .phys_io	    = S3C_PA_UART & 0xfff00000,
	.io_pg_offst	= (((u32)S3C_VA_UART) >> 18) & 0xfffc,
	.boot_params	= S5P_PA_SDRAM + 0x100,
	.init_irq	    = s5pv210_init_irq,
	.map_io		    = smdkv210_map_io,
	.init_machine	= smdkv210_machine_init,
	.timer		    = &s5p_systimer,
};

即这段代码定义了一个 struct machine_desc 类型的变量__mach_desc_SMDKV210,它是SMDKV210这个开发板的软件抽象。

(1).nr=MACH_TYPE_SMDKV210

这个表示这个开发板的机器码是MACH_TYPE_SMDKV210。

机器码值“MACH_TYPE_SMDKV210”在/include/generated/mach-types.h文件中定义。

该文件在内核配置过程中自动生成,维护着该版本内核所支持的全部机器码。

(2).name= "SMDKV210"

这个表示这个开发板的名字叫“SMDKV210”。

(3).init_machine = smdkv210_machine_init

表示这个开发板的硬件初始化函数是 smdkv210_machine_init。

该函数包含了内核中各种硬件的初始化操作。

2.2 为 X210 选择 mach-yyy.c 文件 

我们的目标开发板叫做X210,采用s5pv210这款CPU,按理应该对应着/arch/arm/mach-s5pv210/mach-x210.c文件。

但是在三星版本内核的/arch/arm/mach-s5pv210/中,找不到X210开发板对应的mach-x210.c文件。

为了减少移植工作量,我们在三星版本内核的/arch/arm/mach-s5pv210/中,寻找一个mach-yyy.c文件,使得该文件对应的开发板与X210开发板最为接近(都使用相同的CPU),并以此文件为基础进行移植。

九鼎的X210开发板是根据三星SMDKV210开发板进行设计的,因此要寻找SMDKV210开发板对应的文件,按理应该是三星版本内核的/arch/arm/mach-s5pv210/mach-smdkv210.c文件。

但是分析三星版本内核源码/arch/arm/mach-s5pv210/Makefile文件后得知,CONFIG_MACH_SMDKV210这个宏(在内核配置阶段生成的./config文件中)实际绑定的是/arch/arm/mach-s5pv210/mach-smdkc110.c这个文件,而非mach-smdkv210.c文件。

因此后续将以/arch/arm/mach-s5pv210/mach-smdkc110.c这个文件为基础进行移植。

 

2.3 分析mach-smdkc110.c文件 

在该文件的最后有以下代码:

#ifdef CONFIG_MACH_SMDKC110
MACHINE_START(SMDKC110, "SMDKC110")
#elif CONFIG_MACH_SMDKV210  //选择这个
MACHINE_START(SMDKV210, "SMDKV210")
#endif
	/* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
	.phys_io	= S3C_PA_UART & 0xfff00000,
	.io_pg_offst	= (((u32)S3C_VA_UART) >> 18) & 0xfffc,
	.boot_params	= S5P_PA_SDRAM + 0x100,
	.init_irq	= s5pv210_init_irq,
	.map_io		= smdkc110_map_io,
	.init_machine	= smdkc110_machine_init,
	.timer		= &s5p_systimer,
MACHINE_END

它展开后内容如下:

static const struct machine_desc __mach_desc_SMDKV210	\
 __used							\
 __attribute__((__section__(".arch.info.init"))) = {	\
	.nr		= MACH_TYPE_SMDKV210,\//机器码2456		
	.name		= "SMDKV210",
	.phys_io	= S3C_PA_UART & 0xfff00000,
	.io_pg_offst	= (((u32)S3C_VA_UART) >> 18) & 0xfffc,
	.boot_params	= S5P_PA_SDRAM + 0x100,
	.init_irq	= s5pv210_init_irq,
	.map_io		= smdkv210_map_io,
	.init_machine	= smdkv210_machine_init,//初始化各种硬件
	.timer		= &s5p_systimer,
};

其中,init_machine这个函数指针,指向一个机器硬件初始化函数smdkv210_machine_init。

这个函数绑定了内核启动过程中会初始化的各种硬件的信息,在此函数中添加的硬件才会被初始化,没有在此函数中添加的硬件不会被初始化。

关于smdkv210_machine_init的更多介绍,见驱动栏目中的“Linux设备驱动模型”的内容。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【呼市经开区建设服务项目水、电能耗监测 数采案例】

实施方案 针对能耗采集中的水、电能源数据采集&#xff0c;因客观因素条件&#xff0c;数据采集方面存在较大难度。大多数国网电表485接口由于封签限制&#xff0c;不能实施采集&#xff0c;不让拆机接线&#xff0c;采集实施存在困难。水量能耗采集&#xff0c;存在类似问题&a…

网络原理(3)——TCP协议

目录 一、连接管理 二、三次握手 1、何为三次握手&#xff1f; 2、三次握手有何意义&#xff1f; 三、四次挥手 三次握手和四次挥手的相似之处和不同之处 &#xff08;1&#xff09;相似之处 &#xff08;2&#xff09;不同之处 四、TCP的状态 建立连接&#xff1a; 断开…

Fabric.js在vue2中使用

Fabric.js安装 这里我是基于vue来使用的&#xff0c;先安装上Fabric.js npm install fabric 在main.js中 import fabric from fabric Vue.use(fabric);Fabric 提供了 7 种基础形状&#xff1a; fabric.Circle (圆)fabric.Ellipse (椭圆)fabric.Line (线)fabric.Polyline (多条…

GIS学习

匹配查询&#xff0c;先连接两个表&#xff0c;然后在一个表里面查询 合并两个形状 比较好的colormap http://soliton.vm.bytemark.co.uk/pub/cpt-city/views/totp-cpt.html https://docs.gmt-china.org/latest/cpt/builtin-cpt/ 计算坡度时就要捕捉栅格 重分类时也要捕捉栅…

protobuf原理解析-基于protobuf-c实现序列化,反向序列化

1.一个实例 前面介绍了使用protobuf的流程&#xff0e; (1). 定义proto文件来描述需要序列化和反向序列化传输的消息&#xff0e; (2). 借助proto-c&#xff0c;为proto文件生成对应的代码控制文件&#xff0e; (3). 程序借助生成的代码控制文件和protobuf-c动态库的支持实现类…

HarmonyOS如何创建及调用三方库

介绍 本篇主要向开发者展示了在Stage模型中&#xff0c;如何调用已经上架到三方库中心的社区库和项目内创建的本地库。效果图如下&#xff1a; 相关概念 Navigation&#xff1a;一般作为Page页面的根容器&#xff0c;通过属性设置来展示页面的标题、工具栏、菜单。Tabs&#…

win10 配置 oh-my-posh

win10 配置 oh-my-posh 0. 前置1. 安装1.1. 软件1.2. 字体1.3. 激活1.3.1. Git Bash1.3.2. PowerShell 2. 配置2.1. 效果2.2. 说明2.3. 其他2.3.1. 新版PowerShell2.3.2 conda问题 0. 前置 这个东西毕竟是个&#xff0c;命令行美化工具&#xff0c;所以需要先有一个命令行&…

代码随想录算法训练营第60天 | 84.柱状图中最大的矩形

单调栈章节理论基础&#xff1a; https://leetcode.cn/problems/daily-temperatures/ 84.柱状图中最大的矩形 题目链接&#xff1a;https://leetcode.cn/problems/largest-rectangle-in-histogram/description/ 思路&#xff1a; 本题双指针的写法整体思路和42. 接雨水是一…

ubuntu 20.04 Kimera semantic 运行记录

Ubuntu20.04 Kimera Semantic运行记录 Kimera VIO ROS 配置 MIT Kimera-VIO-ROS 安装 mkdir -p Kimera_ws/src cd Kimera_ws catkin init catkin config --cmake-args -DCMAKE_BUILD_TYPERelease -DGTSAM_TANGENT_PREINTEGRATIONOFF catkin config --merge-develcd src git…

《量子十年》报告更新!IBM精研量子计算,助力行业优化转型

近日&#xff0c;IBM商业价值研究院&#xff08;IBM Institute for Business Value&#xff0c;简称IBV&#xff09;精心出版了一本引人入胜的报告&#xff0c;《量子十年》第四版。这不仅是一本值得一读的书籍&#xff0c;更是对当前行业发展状况的全面总结和重要补充。 这部由…

Linux | Ubuntu安装pylsl

PYNQ开发中使用pylsl过程记录 操作系统为 Linux pynq 5.15.19-xilinx-v2022.1 #1 SMP PREEMPT Mon Apr 11 17:52:14 UTC 2022 armv7l armv7l armv7l GNU/Linux 使用 pip install pylsl 安装后在导入包的过程中会遇到如下错误&#xff1a; RuntimeError: LSL binary library f…

如何实现跨标签页通讯

什么是跨标签页通讯 同一浏览器&#xff0c;可以打开多个标签页&#xff0c;跨标签页通讯就是&#xff0c;一个标签页能够发消息给另一标签页。 有哪些实现方案 localStorage &#xff08;window.onstorage事件监听&#xff09;BroadcastChannel&#xff08;广播&#xff09…

redis在springboot项目中的应用

一&#xff0c;将查询结果放到redis中作为缓存&#xff0c;减轻mysql的压力。 只有在数据量大的时候&#xff0c;查询速度慢的时候才有意义。 本次测试的数据量为XXX. 测试代码: 功能为根据昵称进行模糊匹配。 GetMapping("/get-by-nick")public String getNickN…

【算法专题突破】--- 位运算 --- 丢失的数字(难度⭐) 只出现一次的数字 III (难度⭐⭐) 消失的两个数字(难度⭐⭐⭐)(2)

一&#xff0c;丢失的数字 1. 题目解析 题目链接&#xff1a;268. 丢失的数字 这个问题的理解其实相当简单&#xff0c;只需看一下示例&#xff0c;基本就能明白其含义了。 2.算法原理 首先&#xff0c;我们设定一个长度为n的数组。理想情况下&#xff0c;如果这个数组是从…

机器人路径规划:基于鳑鲏鱼优化算法(Bitterling Fish Optimization,BFO)的机器人路径规划(提供MATLAB代码)

一、机器人路径规划介绍 移动机器人&#xff08;Mobile robot&#xff0c;MR&#xff09;的路径规划是 移动机器人研究的重要分支之&#xff0c;是对其进行控制的基础。根据环境信息的已知程度不同&#xff0c;路径规划分为基于环境信息已知的全局路径规划和基于环境信息未知或…

CSDN学习笔记总索引(2024)——我的创作纪念日(1024)

从2021-05-21至2024-03-19&#xff0c;我的CSDN博文学习笔记中&#xff0c;收集并展示浏览阅读&#xff0c;点赞收藏评论等数据&#xff0c;以浏览阅读量排逆序展示。 (笔记模板由python脚本于2024年03月19日 05:49:24创建&#xff0c;本篇笔记适合熟悉Python&#xff0c;对其基…

一维数组数组名的用途

大家好&#xff1a; 衷心希望各位点赞。 您的问题请留在评论区&#xff0c;我会及时回答。 一、数组名的用途 一维数组数组名的用途&#xff1a; 1、可以统计整个数组的长度。 2、可以获取数组在内存中的首地址。 二、示例代码 #include <iostream> #include <W…

亚马逊等跨境电商平台自养号测评的五个核心因素

一、安全稳定的环境系统 尽管市场上存在大量现成的系统和软件包&#xff0c;卖个软件或设备给你&#xff0c;这种基本上都没有解决风控的能力&#xff0c;因此&#xff0c;小编推荐大家还是自己掌握相关技术&#xff0c;避免过度依赖于外部资源&#xff0c;目前&#xff0c;也…

C语言救赎之路,有些鸟儿是困不住的!(其4) (逻辑运算符+函数)

什么是运算符&#xff1f;诶~&#xff0c;其实我们一直在用运算符&#xff0c;比如我们的 &#xff0c;-&#xff0c;*&#xff0c;/ 等等都是运算符。今天我们就先来讲讲运算符。这是结合我自己的理解&#xff0c;我认为自己讲的肯定比一些教科书讲的要更清楚一些&#xff0c;…