嵌入式编程学习笔记(四)

  • 学习地址:bilibili播主
  • 课程名称:《嵌入式之系统移植》-华清远见出品
  • 课程链接

20200205~20200209

嵌入式设备的启动

学习新得:以下几点解答了一直困惑的嵌入式设备bootloader存在的位置及启动过程

  • bootloader存在的位置大概有了了解,对于使用nor falsh启动的设备,由于nor falsh可以按照字节进行读取,所以在bootloader可以在nor falsh里进行执行,操作系统一般放在另一块存储介质,如nand falsh 或者emmc里;但出于执行效率的考量,一般在前几段bootloader执行完之后,bootloader 会把自己搬移到内存固定位置,然后再初始化更多硬件,然后再把内核搬移到内存,至此把控制权交给内核,内核启动后,加载根文件系统,然后在启动各种应用层应用。
  • 如果使用emmc或者nand falsh启动,bootloader会存在emmc或者nand falsh固定位置,上电后,cpu会把bootloader前4k的boot代码(与地址无关的bootloader)搬移掉CPU内部的4K的SRAM中进行执行,做些简单的工作;进入SVC模式,关掉看门狗,关掉中断,关掉MMC,然后做些简单的初始化动作;如初始化时钟,初始化串口,初始化FLASH,初始化内存等,自搬移到内存,设置好栈,进入C语言阶段;然后进大部分的硬件初始化,把FLASH中操作系统内核等全部搬至内存,运行内核,运行设备树文件,挂载根文件系统。
  • 三个2操作:两段阶段代码-汇编阶段(需要为C语言建立main栈段),C语言代码阶段;bootloader与位置无关的代码和后续大量与位置有关的代码;两次搬移-自搬移和系统内核搬移;两次初始化-基本硬件初始化和复杂硬件初始化。
  • 设备树文件
  • 远程根文件系统
    启动过程

bootcmd:是uboot的启动参数
bootargs:是ubootl传递给linux内核的启动参数,以字符串形式

Linux内核启动

内核启动流程图
内核启动流程图
过程说明:

  • 一般为了节省空间,一般内核代码(如uImage)要经过压缩,所以存在自解压缩过程

Linux内核调试方法

  • 点灯法
  • printk打印输出信息方法:在串口初始化完之前会把打印信息缓存在内存里
 puts			内核解压之前用
 printascii		console初始化之前用
 printk			内核解压之后,输出信息显示在console初始化之后

打印级别

在这里插入图片描述
说明:0级别最高
通过proc在运行时查看和修改日志级别,只需修改一个数字表示级别

cat /proc/sys/kernel/printk							4 4 1 7
echo "7 4 1 7" > /proc/sys/kernel/printk			写入方法
  • OOP内核异常信息

根据PC指针的显示,当前出错的函数;再根据交叉编译工具链即可获取出错的代码的位置;
vmlinux是编译后生成的没有经过压缩的内核镜像文件;
c024225c 是出错代码的地方,通过打印的堆栈信息的PC值获取

找出出错位置举例
则可以获取出问题的文件及代码位置
图片

linux内核移植

平台无关的部分

Linux内核配置编译

在自己工作目录解压缩:tar -xvf linux-4.4.213.tar.xz

  • 修改Makefile指定交叉编译工具链
vim Makefile
#ARCH ?= $(SUBARCH)
#CROSS_COMPILE ?= $(CONFIG_CROSS_COMPILE:"%"=%)
改为
ARCH ?= arm
CROSS_COMPILE ?= arm-none-linux-gnueabi
  • 导入配置eg:make exynos_defconfig

配置列表见arch/arm/configs/ 目录,找最相似的,此处arm仅是举例,具体CPU具体选择,exynos_defconfig是我们找到符合的配置;
也可采用cp arch/arm/configs/exynos_defconfig .config 的方式导入

  • 配置内核:make menuconfig
  • 编译内核:make uImage
  • 编译设备树:make dtbs

生成的设备树文件在 /arch/arm/boot/dts/
dts是描述文件,dtb是生成的可在板子上运行的文件
设备树(DeviceTree):是描述硬件信息的数据结构;用于管理硬件拓扑和硬件资源信息;设备树由一系列被命名的结点(node)和属性(propetry)组成,而结点本身可包含子结点;所谓属性,其实就是成对出现的name和value
在内核源码中的 Documentation/devicetree/bindings/ 中有简单的说明

网卡驱动移植

make menuconfig
  • 配置内核支持网络
  • 配置网络协议支持TCP/IP
  • 配置支持网络文件系统NFS
  • 配置支持(eg:dm9000)网卡驱动(此种情况是内核代码中存在相应的网卡驱动,若没有,要自己编写编译进内核)

平台相关的部分

配置设备树描述硬件和CPU的连接情况

在目录/arch/arm/boot/dts/对应的设备树上进行修改

  • 修改设备树

可以通过原理图、框图拓扑和CPU等芯片手册知道每个链路、每个设备的地址信息、ID信息
CPU控制外部设备的bank概念和内存控制器的bank概念不是一回事
一般来说,(网卡)驱动程序是与硬件平台无关的,具体(网卡)硬件怎么连接,是由设备树文件说明的;即不同产品对应不同的设备树
对应中断含义可参考Documentation/devicetree/bindings/arm/gic.txt 如下图中的interrupts = <6 4>中的4的含义-高电平有效

下图以网卡作为举例
举例

  • 编译修改后的设备树 make dtbs ;然后使用新生成的设备树.dtb文件

第三方驱动移植

如果内核里已经支持相关驱动,直接选配就可以;如果不支持,就得自己找一个或者开发一个,然后移植到内核

黑盒移植
编译驱动进内核
  • 选择驱动存放目录,一般放在drivers目录下相关目录(或任意目录)

一般公司级的开发,都会自己创建一个适合本公司的内核驱动目录,用于管理内核驱动源码

  • 改Makefile

linux内核源码中每个目录下都有Makefile,负责具体的编译文件的管理
最终编译的时候要在总的Makefile中进行编译;可观察打印信息查看新加的驱动是否编译进来

  • 改Kconfig(界面可配置,此方法更加高效好用,且便于管理内核驱动)
    Kconfig

linux内核源码中每个目录下都有Kconfig,负责在menuconfig界面里显示对应的选项

  • 将相应驱动目录下的Makefile和Kconfig做关联

obj-y 是指定在编译时必须编译
obj-$(CONFIG_XXX) 是根据menuconfig的选择情况进行编译

Makefile

  • 编译应用程序用来对驱动进行功能调用进行测试
编译驱动为独立的模块
  • 配置为模块方式

menuconfig< >有三个选择,编译或者不编译,以及编程成模块
menuconfig[ ]仅有两个选择,编译或者不编译
是通过Kconfig中的tristate关键字表示的

tristate

  • make modules编译为模块

编译完之后的模块化的内核驱动文件后缀是.ko;产品可以选择动态的加载该驱动模块

insmod xxx.ko Linux提供的动态加载驱动到内核模块的命令
mknod 创建设备结点 eg:mknod dev/led c 501 0 (c字符设备、501主设备号、0副设备号)
内核驱动程序都是被动运行的,由上层应用触发

驱动模块三要素:加载入口:module_init() 卸载入口:module_exit() 免费开源声明:MODULE_LICENSE()

  • 创建设备结点(应用访问驱动的入口)

mknod 创建设备结点

  • 运行测试驱动的应用程序
白盒移植
打印跟踪
驱动框架
字符设备
  • 内核设备驱动框架
  • 硬件设备层:每个设备都有一个设备号
  • 内核层:驱动框架要对每个设备进行注册设备号
  • 应用层:
注册设备号->初始化该设备->操作设备

内核需要使用ioremap内核函数将芯片手册提供的硬件设备的物理地址转换成内核可以操作的地址

平台设备
  • 解决了什么问题

硬件设备更新后,减少驱动更改的代码量;
因为驱动程序里面包含具体设备的物理地址等信息,如果硬件设备设计更新,一般来说都要修改内核驱动代码

  • 平台设备驱动框架

怎么做的:把硬件信息从驱动里剥离出来,放到设备树文件当中,这样让驱动程序间接的获取设备树文件中的硬件信息,硬件变化一般只要更改设备树文件就可以了,概括地说就是分离概念,好处便于维护

根文件系统

根文件系统概念

根文件系统作用

根文件系统(root filesystem)是存放运行、维护系统所必需的各种工具软件、库文件、脚本、配置文件和其它特殊文件的地方(载体仓库),也可以安装各种软件包;是内核起来之后挂载的第一个文件系统,之后还可以挂载其它文件系统

可以使用busybox工具制作根文件系统

设备访问

主设备号和次设备号
  • Linux系统是通过主设备号和次设备号来区分设备的

主设备号(major):系统内核用来区分哪类设备
次设备号(minor):区分某类设备中的哪个设备
可在内核的文档中看到:Documentation/devices.txt

创建设备结点

设备文件不能在加载驱动程序的时候自动创建,要通过指令创建

  • 创建设备文件的一般语法
mknod /dev/<device> [c|b] <major> <minor>

eg:

mknod /dev/ttySAC0 c 4 64
mknod /dev/hda1 b 3 1

Linux系统的引导过程

引导

init是系统起来之后工作的第一个应用程序

根文件系统的制作

制作根文件系统的内容
  • 采用busybox创建基本命令
  • 创建基本的目录 /lib /etc /var /tmp /dev /sys /proc
  • 添加glibc基本动态库
  • 创建基本的设备结点
  • 添加启动配置和脚本程序/etc/inittab/etc/fstab/etc/init.d/rcS
测试rootfs文件系统的正确性
制作需要的rootfs的类型的格式

不同形式的根文件系统
系统

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
《基于模型的系统工程最佳实践》从方法论的角度,描述了基于模型的系统工程最佳实践。主要从系统工程的视点出发,把系统开发的前期系统工程的工作任务、责任范围,以工作流的方式,解剖得淋漓尽致,为系统的后续开发和系统的确认与验证,提供了无缝衔接。本书以系统工程实践者为对象,通过众多截屏、注释和最佳实践技巧,帮助读者清晰理解工作流的细节。本书的目的是帮助读者在集成系统和软件开发中应用基于模型的系统工程标准建模语言SysML。 第1章 绪论 1.1 范围 1.2 内容概述 第2章 HarmonySE基础 2.1 Rational集成系统嵌入式实时开发流程:Harmony 2.2 基于模型的系统工程流程 2.2.1 需求分析 2.2.2 系统功能分析 2.2.3 设计综合 2.2.3.1 架构分析(权衡分析研究) 2.2.3.2 架构设计 2.2.4 系统工程交付 2.3 SysML应用于基于模型的系统工程的基本工件 2.3.1 需求图 2.3.2 结构图 2.3.2.1 模块定义图 2.3.2.2 内部模块图 2.3.2.3 参数图 2.3.3 行为图 2.3.3.1 用例图 2.3.3.2 活动图 2.3.3.3 序列图 2.3.3.4 状态图 2.3.4 需求分析系统功能分析层次的工件关系 2.4 服务请求驱动的建模方法 第3章 Rhapsody项目结构 3.1 项目结构概览 3.2 需求分析套件包 3.3 功能分析套件包 3.4 设计综合套件包 3.4.1 架构分析套件包 3.4.2 架构设计套件包 3.5 系统层定义 第4章 案例:安全系统 4.1 案例工作流 4.2 创建Harmony项目结构 4.3 需求分析 4.3.1 DOORS:涉众需求的导入 4.3.2 DOORS:系统需求的导入 4.3.3 关联系统需求到涉众需求 4·3.4 DOORS一>Gateway->Rhapsody:导入系统需求 4.3.5 系统级用例定义 …… 第5章 交付到子系统开发

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值