学习嵌入式linux需要先学什么?

韦东山:一篇6000字的长文章告诉你如何学习嵌入式linux。

链接:Web链接

第1章MCU和Linux的区别

1.1什么产品用的是MCU或者Linux?

所有的电子产品,使用的技术可以考虑要么是单片机,要么是Linux;GUI主要是QT/Android,都运行在Linux上。

也许你不接受!不是有ucos,vxwork,wince,IOS吗?下图是关于操作系统的比例,来自2016。没有找到更新的图表,但是很有参考意义:

我们说的单片机不使用操作系统,上图没有体现。但是单芯片设备的使用肯定是远远多于Linux的。很多人也是先学单片机,从单片机进入电子工程师行业。

日常生活中,哪些产品使用单片机和Linux?以下是一些例子:

我们设计一个产品,用单片机还是Linux,取决于成本:硬件成本,软件成本,维护成本,升级成本。而不是根据个人喜好选择:我喜欢单片机,所以我排斥使用Linux;我喜欢Linux,所以排斥用单片机。为了有更多的选择,我们需要既懂单片机又懂Linux。

1.2在硬件操作上和Linux差不多。

以照明为例,

不管是单片机还是Linux,我们都要做同样的事情:

①看原理图,确定是哪个引脚,输出什么电平。

②查看芯片手册,确定如何操作寄存器。

③写一个程序

但是,如何写程序和Linux有很大的不同。

1.3照明用单片机和液晶显示器

用单片机开发程序时,一开始就写一个主函数。以下是一些简化代码:

led程序中的init_led,led_on,led_off函数都是自己写的。你可以取任何你喜欢的名字,随你怎么写。

LCD程序里的功能也是你写的,完全自由发挥。

很多单片机项目都不是很复杂。两三个人自上而下全部做,大部分时间里面的功能都是直接读写寄存器。

许多单片机项目严重依赖硬件。换了一个芯片之后该怎么办?重写一组代码。

在单片机程序中,没有应用程序和驱动程序的概念,很可能一个人做硬件设计、模块调试(或驱动)、功能开发(或应用)的所有工作。

Linux中的1.4照明和使用LCD

在Linux中,不允许应用程序开发人员直接操作硬件。比如你要点灯,对不起,不能直接访问寄存器。你需要通过驱动程序访问寄存器。

为什么?有几个原因:

Linux系统中运行的程序很多,需要保证质量差的程序不能破坏系统:

假设你写的程序是坏的,那我不能让你随便访问寄存器,让系统崩溃怎么办?你本打算点灯,但你看错了登记簿。如果你关掉电源,你应该做什么?

所以操作硬件的工作应该由可以信任的人来做:既懂硬件又懂软件的驱动工程师。

(2)保证程序的可移植性:

写应用程序的时候,大家都用统一的函数,以后换个芯片,应用程序就不用改了;按照这个接口提供驱动就可以了。

③团队合作:

。使用Linux系统的项目一般都比较大,而且术业有专攻,一个人不可能从上到下都掌握。比如你在做人脸识别项目,有人擅长图像处理。他不在乎你要用多少种相机,给他一个图像就行。各种摄像头的硬件操作方法不一样,交给驱动工程师。

因此,在Linux中,应用程序和驱动程序是分离的。

以LED和LCD程序为例,简化代码如下:

也许你已经大概猜到了,应用是怎么调用驱动的?通过标准接口:

①打开:

打开驱动程序。

②读/写:

读取和写入数据。

③ ioctl:

传入各种参数,得到各种参数。

④ mmap:

内存映射,比如映射后应用可以直接读写LCD的显示内存。

看啊!从这些接口上,我们根本看不到寄存器的操作。底层程序驱动程序将根据这些调用设置寄存器并操作硬件。

所以,我这个高大上的应用工程师,又何必去读原理图,读片内手册,读写寄存器,甚至调试硬件bug呢?把脏活累活留给驱动工程师。客户的需求千变万化,我没有足够的时间做996。

啧啧,作为一个既懂软件又懂硬件的驱动工程师,我当然不能把这么重要的工作交给你。如果我的系统崩溃了怎么办?

开玩笑,开玩笑,开玩笑,应用工程师和驱动工程师各有利弊,大家都在努力做产品。有一个趋势是你需要从上到下的去理解一个任务,也就是所谓的全栈工程师。

还是以LED为例,应用和驱动的配合如下图所示:

在Linux中,“一切都是一个文件”。要访问某个硬件,还需要打开文件,读写文件。应用程序应该根据标准文件接口访问驱动程序:open/read/write/ioctl/mmap等。

既然如此,怎么写驱动呢?最简单的办法是:如果APP要调用open打开驱动,在驱动程序中提供一个xxx_open函数,初始化硬件;APP调用write写数据,驱动提供xxx_write函数接收数据,操作硬件。

用xxx_open和xxx_write组成一个驱动,就是驱动框架。

如何实现这些xxx_open和xxx_write函数?我们要做的和单片机差不多。我们要看电路图和芯片手册,然后读写这些函数中的寄存器:这叫硬件操作。

所以,Linux驱动=?驱动框架?+?硬件操作。

有单片机基础的人对硬件操作比较熟悉,可以把重点放在驱动架上。

高能预警:驱动框架不简单,对LED来说简单,但还有更复杂的驱动,要考虑“通用”,这是很致命的。

第2章嵌入式Linux快速入门

这几天和群里的同学聊天,有一个同学的学习方法很好:先看广度,再探深度。有时候要“不求人解”。很多时候,保持疑惑,先学会,这些问题自然就解决了。

比如课程涉及到组装知识。想要彻底理解,需要学习ARM架构和编程。当你学完这本书的时候,你的同学可能已经可以开始工作了。

2.1的短期目标是什么?

先定下学习目标:快速了解嵌入式Linux的开发流程,知道要学什么,具备与从业者交流的能力。

下面我们用类比和逻辑来推导嵌入式Linux系统的构成,对,“推导”。

从上图可以看出:

①构成:

嵌入式Linux系统

= bootloader+linux内核+根文件系统(其中包含APP)。

②引导加载程序:

它的目的是启动内核,哪里等着读内核?在哪里读?转到Flash和其他外设读取内核并保存在内存中。所以需要具备Flash中外设的驱动能力,为了调试方便会有网络功能。

所以可以认为booloader =裸机集,是一个复杂的单片机程序。

③ Linux内核

Linux内核的主要用途是启动应用程序。APP保存在哪里?将其保存在根文件系统中。“根文件系统”保存在哪里?在Flash、SD卡等设备中,甚至可能在网络上。所以Linux内核应该具备Flash和SD卡中这些设备的驱动能力。

不仅如此,Linux内核还具有进程调度和内存管理的功能。

所以:Linux内核=驱动集+进程调度+内存管理等。

2.3要不要学bootloader?

Bootloader有很多种,俗称u-boot。

实际工作中,u-boot基本都是修改甚至不改。但是,u-boot本身就很复杂。比如为了方便调试,支持网络功能。一些内核存储在FAT32分区中,因此它应该能够解析FAT32分区并读取FAT32分区的文件。

我花那么多精力学u-boot,工作中却几乎用不到,对新手很不友好。

所以对于新手,我建议:了解u-boot的功能,使用u-boot的命令,就够了。

如果你的工作是修改和改进bootloader,那就再研究一遍。

2.4想学Linux内核和驱动吗?

我们之前说过Linux内核=驱动集+进程调度+内存管理等。如果想学习Linux内核,从驱动入手是个不错的方法。

但是每个人都要学Linux内核和Linux驱动吗?显然不是。

作为初学者,认识几个简单的司机有利于工作交流;理解中断、进程、线程的概念,对驱动开发和应用开发都非常有益。

所以对于新手来说,建议前期只学这几个驱动:LED、按键、中断。

① LED驱动器:

这是最简单的驱动程序。

②关键驱动因素:

也比较简单,从中引入“中断”。

③中断:

从“中断”可以引入睡眠-唤醒、进程/线程、轮询机制、异步通知等概念。这些概念对于驱动程序开发和应用程序开发都非常重要。

所以对于新手来说,我建议一定要学习这几个驱动:LED、key、中断。

入门之后,如果想从事内核开发和驱动开发,可以钻研几个驱动(输入系统、I2C总线、SPI总线等。).掌握了几个大的驱动之后,你就对内核例程有所了解了。当你研究其他部分(比如流程管理、文件系统)的时候,你会发现,套路就是这么通用。

摄像头(VL42)和声卡ALSA驱动是Linux中两个比较复杂的驱动,难度很大。如果作品与此有关,我们将再次研究它们。

2.5,要不要学Linux应用?先学点基本功。

要学,哪怕以后只想学内核,也需要一些基本的应用开发和编写技巧:

①访问基本设备,如LCD和输入设备。

②进程、线程、进程通信、线程同步、互斥。

③睡眠-唤醒、轮询机制和信号。

④网络编程

① ② ③部分知识与驾驶密切相关,两者相辅相成。

掌握了基本的驱动开发能力和基本的应用开发能力后,在工作中就可以友好地与人交流,不会显得不知所措。

2.6.应用程序是如何启动的?要了解根文件系统

你辛辛苦苦写了一个应用,如何把它放在板子上,让它开机自动启动?

你写的程序,它依赖于哪些库,这些库放在板的哪个目录下?

如何做一个可升级的系统?即使升级中途断电,也要保证程序至少能运行老版本吗?

这些都需要我们去了解根文件系统。

我们来看看init进程:它读取配置文件,根据配置文件启动每个APP。

了解了init过程,你就明白了根文件系统的组成,你就可以随意裁剪系统,为你的项目做出最精简的系统。

第三章学习方法

3.1,先别刨根问底。

嵌入式涉及的东西太多。如果心里没有主线,就要把所有的东西都学透,最终忘记自己想学的东西。

嵌入式涉及硬件知识和软件知识,软件涉及汇编、ARM架构、C语言、Makefile和Shell。分为bootloader、内核、驱动、基础APP、GUI。

比如我们会用Makefile来理解它的基本规则,我们会用我们提供的Makefile。

你不需要深入研究那些make函数,因为有现成的makefile供你在工作中使用,你也不需要自己写一个makefile。为什么要花几天时间深入研究呢?

例如,我们将使用bootloader。我们要花几个月的时间来研究u-boot吗?工作中基本不需要换u-boot,用那些命令就可以了。

甚至有的同学去买个shell的书先学习shell命令。为什么?我们在视频中使用什么命令?不懂的时候就去百度一下这些命令。

不要脱离初学者的主线:应用基础和驾驶基础。有了这两个基础,当你想深入研究一个部分的时候,再花时间。

3.2,思路清晰,不怕抄代码。

请自行编写视频中的代码一次和多次。为什么我现在写驱动这么好?2009年我在华清预见班的时候,

我每节课都要给学生写一遍那些驱动,闭着眼睛十几遍就知道内核例程了。

记不住那些功能?我也记不起来了。我总是指同一类司机。不是闭卷考试。

但是要有一个清晰的思路,你写这个程序是想完成什么功能,这些功能是怎么实现的?这需要澄清。

有了想法再写代码。不知道怎么写。不要紧,看看视频,看看例子,然后关闭视频,看看自己能不能写出来。

3.3,我很清楚自己的方向,所以只能带你到这里。

我的专业是操作系统,就是快速带领大家掌握一些项目开发的基础知识。

如果你决定钻研什么,我不能带你去太久。你应该去看看源代码和这方面的专业书籍。

比如你要钻研内核的内存管理,它有页表映射(需要看ARM架构的手册)、SLAB分配器、vmalloc/malloc实现、mmap实现、缺页中断、父进程与子进程之间的页面管理等。,而且内容很多。有时候连书都没有,需要直接啃代码。

当你想从事某个行业的时候,你需要深入学习行业相关的知识。

比如CAN总线可以写成一本书:CAN协议、CAN报文、Socket CAN、车身网络拓扑、CAN应用报文、CAN网络管理报文、CAN诊断报文。

想做物联网网关,需要深入研究MQTT。MQTT协议比较简单,但是MQTT协议英文原版有130多页,中文版有近100页,很短的一本书。

每个行业都有自己的商业逻辑。要想掌握其中一项基本的编程能力,需要结合具体业务进行深入学习。

-☆ END ☆-