精华内容
下载资源
问答
  • 如何学习嵌入式嵌入式之路从入门到放弃....

    千次阅读 多人点赞 2017-09-14 19:26:29
    什么是嵌入式?  嵌入式分为广义和狭义两种。广义的嵌入式就是片上系统(system on a chip),包括单片机、PSOC、NIOS、Microblaze等。而狭义的嵌入式就是ARM9、cortex A8等特定的跑操作系统的芯片。这里主要介绍...

    什么是嵌入式?

            嵌入式分为广义和狭义两种。广义的嵌入式就是片上系统(system on a chip),包括单片机、PSOC、NIOS、Microblaze等。而狭义的嵌入式就是ARM9、cortex A8等特定的跑操作系统的芯片。这里主要介绍狭义嵌入式的学习路线。

            还是主流的方法,先学会使用它,再深入研究底层。

            常用的操作系统有linux、WIN CE、安卓、Vxworks、QNX、OSE等,目前资料最多的是linux,所以下面以linux为例。

    一、安装虚拟机和linux系统。

            一般人用的电脑都会装Windows系统,要想在Windows上跑其它系统,得安装虚拟机。而目前主流的虚拟机有vmware、VirtualBox、hyperV等,你可以随便选一个安装。然后去官网下载个人版的linux镜像(.iso文件)并把它安装在虚拟机里面即可,这里给出主流linux系统的官网链接:ubuntufedoracentosdebiansuse。如果你没有用过linux的话,推荐使用ubuntu。因为RedHat要收费,并改名为RHEL,所以这里不作介绍。

             先下载一本《鸟哥私房菜》。然后进入第二、三、四阶段(前期的学习不需要开发板)。

    二、学会使用linux常用命令。

             这里,必须改改在Windows下点鼠标的习惯,在linux下做事得用命令行。此外,在linux下载软件,不需要在百度下载,而是用linux自带的软件包管理工具(如:apt-get、dnf、rpm等)。如果你用ubuntu的话,得修改软件源(下载软件的网址),因为国外的源比较慢,百度上有详细说明。接下来,得学会最基本的命令,如:ls、cd、find、grep、ps、diff、fdisk、ifconfig等。跟着教材多操作几遍就会了,没有很深的理论知识,不需要掌握所有的命令,也不需要记住所有命令的选项,用到的时候会查就可以了。有空的话可以上ubuntu社区或者linux公社

    三、学会使用linux常用工具。

    1、编辑器(写代码必备的)。有gedit,vim,emacs,sublime等,推荐学vim

    2、gcc和gdb。gcc是编译器,gdb就是代码调试器。

    3、makefile、autoconf、automake。这里可不像VC++6.0这种工具,点个鼠标就给你编译好。在linux下,你得用makefile和make工具,来编译代码。其中autoconf和automake可以自动生成makefile。

    4、ssh、tftp。如果你在ARM开发板上弄了个Web服务器,那么,你就可以用这些工具去访问它。其中,ssh工具建议用SecureCRT或者MobaXterm

    5、samba。要想用linux跟windows交换数据,还可以搭建samba服务器。

    6、版本控制器。有svn,cvs,git等,推荐学git。有了git,你就不必手动备份代码了。

    四、学会编写shell脚本。

             在实际工作中,复杂的系统管理操作,不会一行一行地敲命令,而是用脚本(命令是基础)。脚本也是一种编程语言,只不过是解释型语言。相比C/C++、C#、JAVA这类高级语言,脚本要易学很多(因为增加了语法糖)。在linux下,shell也有很多种,如:bsh、bash、csh、tcsh、ksh、zsh等,一般是学bash,其它的遇到再学也不迟,因为都是大同小异的。此外,bash语法比较奇特,很多符号(如:$#,$0,$?等)比较难记,不过也没必要特意去死记它,有个印象就可以了,用到的话再查手册,这里重点掌握正则表达式。如果有时间的话,建议再学python脚本,python的语法要容易很多,用途也比bash广很多。推荐《Shell脚本编程诀窍》。

    五、学会linux下C编程。

             尽管学会bash已经能做很多事情了,但是驱动和内核开发还是用C语言,因为那时候系统还没起来,bash是用不了的。此外,C语言的执行效率比bash要高,网络编程的Socket也常常用C语言开发。在这里,得掌握基本的文件操作、进程/线程控制、Socket等。推荐《Linux环境C程序设计》、《UNIX环境高级编程》、《UNIX网络编程 卷1》、《UNIX网络编程 卷2》,或许这些教材有点难,但是,请不要钻牛角尖,不懂的暂时跳过,在学完下一阶段的理论之后,再来看,之前不懂的东西就变得容易。

    六、增强理论知识。

            因为有的人打着嵌入式硬件工程师的名号装逼,其实嵌入式硬件就是普通硬件工程师做的工作。我们这里都是讨论软件方面的内容,而且嵌入式是以软件为主导的(工资上有较大差距)。如果对硬件感兴趣的,可以参考本博客《如何学习硬件设计——理论篇》和《如何学习硬件设计——实践篇》,这里不要求掌握硬件,有一定程度的了解即可。

    1、单片机。具体的学习路线请参考本博客的《如何学习单片机》。不想学单片机的话,可以学计算机组成原理。

    2、数据结构。主要掌握表和树,其中链表会在操作系统的调度算法中用到。

    3、操作系统。全部都是重点,必须深入研究,才会对linux有个较全面的认识。

    4、编译原理。有时间的话,最好多看看,没空的话,也得了解一下。对于提高编程能力,有一定的帮助。

    5、数据库。除了基本的数据库理论之外,还得掌握SQLite或者Oracle。

    6、ARM体系结构。介绍ARM的架构和指令集,在移植uboot和驱动中会用到,不做这两项工作的话,可以不学。

    7、计算机网络基础。开发中用到的socket、ssh、tftp、http就会涉及到网络相关的知识。

    8、接口应用。如:串口、zmodem、IIC、SPI、1-wire、USB、HDMI、CAN、IIS、PCIE、蓝牙、陀螺仪等。

               学完上面这些理论之后,得再复习一下linux下C编程,你会有更大的收获。

               先下载一本韦东山的《嵌入式Linux应用开发完全手册》,还要买一块2440的开发板(虽然s3c2440已经停产,但是这芯片依照是资料最多的一块),然后进入七、八、九、十阶段。其中第七、八、九阶段,使用开发板自带的bootloader即可,暂时不必研究它。

    七、文件系统。

           在学习操作系统原理的时候,已经有介绍文件系统了,而且不需要深入研究文件系统的具体算法,只需要了解其特性再学会使用它就可以了。如:NFS、FAT32、NTFS、yaffs2、ext4、ZFS等。

    八、内核裁剪。

            一般初学,可以先掌握内核剪裁(具体工作就是填写若干个选项)。剪裁只是去掉内核部分不需要的功能,以减少代码体积。这里只要求你对内核的各个功能选项都很熟悉就可以了。如果剪裁还不能满足要求的话,得阅读内核源码,修改内核了。推荐《Understanding the Linux Kernel》和《Linux Kernel Development》。阅读内核源码,推荐windows下的source insight。

    九、驱动开发。

            由于系统还没起来,所以驱动能用到的API(内核的部分API,如:kprintk、kmalloc等)并不多,很多函数还是得自己写的,其中,会经常访问临界资源,所以得掌握自旋锁、睡眠锁。此外,驱动程序出问题的话,整个系统就挂掉了,所以还要掌握各种调试驱动的方法,如:goto语句、日志系统、KDB等。接下来就要熟悉掌握字符设备和块设备的驱动程序了。推荐《小白的博客》和《Linux Device Drivers》(不建议看中文版)。

    十、移植bootloader。

            单片机也有bootloader,在keil C下的startup.a51,主要是做一些初始化工作。那么,在ARM上面的bootloader也是一样的功能,同样,也没有那么重要所以把它排在后面。常用的bootloader有vivi和uboot,一般学习uboot,主要掌握uboot的启动流程和移植。在经过前面的学习,那么uboot对你来说已经非常容易的了,一般只需要学会使用uboot或者用已经移植好的uboot,不需要深入研究它。推荐看uboot自带的帮助文档以及《深入理解BootLoader》。阅读uboot源码,推荐windows下的source insight。

    十一、图形界面开发。

            常用的GUI图形库有:GTK++、QT、JAVA、安卓等。有C++基础的,建议学习QT,不会C++的,建议学JAVA。在前期的GUI开发,可以不需要使用开发板,而2440下适合跑QT,如果要跑JAVA、安卓的话,建议换一块开发板,可以考虑Exynos4412开发板。此外,你还可以用python自带的TKinter来开发图形界面。推荐《QT5编程入门》、《疯狂JAVA讲义》、《疯狂Android讲义》、《python编程入门》。

             因为安卓系统是在linux的基础上封装了一层API,所以,如果做安卓驱动,就得掌握linux(上面前十个阶段)。如果只做安卓app,你只需要使用android studio或者eclipse配合安卓模拟器(最好用安卓手机),就可以了,不需要学习linux,也不需要开发板。

              在你做过几个GUI项目之后,再学习UML设计模式这会大大增强你的代码架构能力。

    十二、Web开发。

             有的时候得在ARM板上搭个web服务器,这里,得学习HTML、CSS、Javascript、XML、Ajax、PHP等。看起来内容很多,但其实并不多,因为这些语言都很容易上手。初学可以使用Adobe的Dreamweaver做开发,上手之后一个sublime text配合firefox浏览器就可以了(还要学习MVC模式)。此外,还得会用bash或者python编写CGI程序,这样才可以在网页上调用到底层的C语言接口。推荐《疯狂HTML 5/CSS3/JavaScript讲义》。

    十三、杂谈。

              本文没有涉及流程图绘制软件文档生成工具等(这两个东西在工作中会经常用到)。

              由上文可知,嵌入式软件涉及很多计算机相关的知识,这对于电子专业的学生来说,无疑相当于跨专业那么大难度。此外,就算你掌握了上面所提及的知识,那也只是打开一扇小小的窗户而已,还有很多事情做不了的。比如:二维码识别、视频采集卡等。

    BTW,嵌入式的工作也分成几个岗位,分别是系统工程师、驱动工程师、软件工程师(负责网页或GUI开发)、UI工程师(又称美工)。

    系统工程师:熟悉操作系统的内核原理、熟读内核源码。主要职责为系统打补丁或者添加新功能,如:热升级、提高系统的容错性等。一般的公司是不做这种开发的。

    驱动工程师:熟悉各种外设的驱动开发,为内核和GUI提供接口。由于很多IC厂商提供了相关芯片的驱动程序,而导致很多驱动工程师下岗(需求量减少)。

    软件工程师:熟悉各种编程语言和GUI图形库、框架(不是会查文档就可以的,而是要求非常熟悉框架)。由于项目需求经常变更,开发效率跟不上变化,所以软件工程师的需求量大大增加。

    UI工程师:主要负责美化界面。美术特长生更适合这类工作。

    展开全文
  • 嵌入式Linux入门:概述

    万次阅读 多人点赞 2017-06-01 20:48:25
    嵌入式入门文章比比皆是,不同的人有不同的入门方法。本文就结合笔者经历写一写个人的嵌入式Linux入门的一些步骤和经验。不当之处,望方家指正。 在正式开始之前,先花一点时间写写笔者学习的经历。我是计算机专业...

    李迟按:

    嵌入式入门文章比比皆是,不同的人有不同的入门方法。本文就结合笔者经历写一写个人的嵌入式Linux入门的一些步骤和经验。不当之处,望方家指正。

    在正式开始之前,先花一点时间写写笔者学习的经历。我是计算机专业,因此,对于模拟电路、数字电路、操作系统原理、数据库原理、编译原理、计算组成原理、计算机体系结构、数据结构等等课程,都是必修课。我虽然都不精通,但起码是学习了。

    我从大二开始就已经接触51和AVR单片机,当时机缘巧合,由同专业的同学——也是我老乡带我开始的。然后开始画板、做板、焊板、写程序这些路子,前后陆续接触大约一两年时间,这些经历对于自学嵌入式Linux打下很好的基础。——事实上,在我开发单片机时,我已经计划好要学嵌入式,而且是偏向软件方向。

    同时我也开始安装Linux,自己捣鼓,包括虚拟机安装、物理机安装。因为考试和困难放弃一段时间,但最后还是继续。

    后来大三买了一块ARM9的开发板,自己捣鼓(不用“研究”,是因为以纯粹的门外汉去进行的)uboot、内核、根文件系统。本着不服输的精神,虽然一度放弃,但还是坚持下去。

    在毕业时慢慢摸到一些门道。但此时技术还不够,代码量还不够,后来工作多年,大量接触各式不同的技术,虽然并没有很深入,但足够养成习惯,——解决问题、研究新技术的方法、习惯。

    综上,我走的路子概括为:单片机-->使用Linux-->嵌入式Linux(u-boot->kernel->rootfs)。软件知识:基础必修课->linux环境编译->Linux驱动。

    从上文可以看到,笔者是作为计算机专业的学生而进入嵌入式Linux领域的。但并不是说一定要在学校学习那些课程才能入门。无论学习什么知识,都是靠自己进行的,但有了过来人指点、带你入门,往往省时省力很多——而这正是本文的目的。

    下面进入正文部分。

    一、系统环境

    1、环境搭建

    开发嵌入式需要大量辅助软件,一般来说,我们是在电脑上开发好程序,然后通过某些方式将程序下载到开发板上运行。按这个顺序列出一些我认为必须的:

    Linux系统:主要作为程序开发的系统,选择多人使用并资源丰富的版本,建议ubuntu或fedora,目前我使用ubuntu。可以使用在虚拟机或物理机上。

    虚拟机:有条件的推荐使用物理机安装,但一般经常使用vmware这类虚拟机软件,通过这个软件安装ubuntu系统,然后设置共享。然后在这个系统上交叉编译。

    共享方式:有的人喜欢用vmware自带共享功能,有的人喜欢用samba共享。个人建议在ubuntu中设置samba共享,这样可以在windows上将ubuntu共享目录映射成为其中一个盘符,这样做,就可以在windows下操作linux系统的目录、文件了,不过前提是需要网络性能良好。另一种常见的共享方式是nfs,多用于主机和开发板之间的文件传输。

    开发IDE:有的人建议在linux系统中用vim或emacs,但作为初学者入门,不要如此,使用vim、emacs学习成本高,而会打击积极性。在samba共享情况下,建议使用Notepad++、source insight进行代码编辑

    交叉编译:交叉编译是嵌入式一个很重要的概念。由于我们编译的程序是在开发板(开发板又称目标板)上运行的,但开发板又没有环境进行编译,所以带出“交叉编译”概念。即在一台linux主机系统上使用交叉编译器对代码进行编译,但编译得到的二进制文件无法在该主机运行,只能在开发板上运行。不同的板子使用的交叉编译器不同。一般使用商家自带的交叉编译器。

    下载手段:根据应用场合,可以用jtag烧录器下载程序(适用如u-boot开发)。可以使用tftp方式下载程序(适用kernel开发)。在开发板系统启动后且网络正常情况下,可以使用tftp下载、nfs拷贝等方式进行调试(适用于应用层程序开发)。

    另外对于USB转串口线、网络这类的东西,就不一一详细说明了。

     

    掌握程度:不同人使用的开发环境不尽相同。原则上只要是自己熟悉的环境就可以了,以提高开发效率为准则。

    推荐软件:vmware、notepad++、source insight、tftpd32(均为windows系统软件)。

    2、系统使用

    工欲善其事,必先利其器。系统环境使用熟悉程度越高,越能提高开发速度。举个例了,曾经遇到过别人在设备上调试应用程序,步骤是:编码、编译、制作软件包、用工具升级软件包到设备上,设备上电看效果。这一系列步骤中,制作包、升级软件包耗时很长,对于调试十分不利。如果使用NFS,时间能省至少三分之二。所以说,环境的熟悉是十分重要和必要的。

    本节主要针对Linux系统,对于入门者而言,Linux系统的使用是一个大坎。但要知道,嵌入式开发是离不开linux系统的,是必须学的。目前网络资料十分广泛,几乎遇到的问题都在找到答案,但质量往往良莠不齐,有些甚至会误导人。因此,建议一边学一边做笔记,把自己的疑问、心得、步骤都记录下来(比如,记录第1小节提到的nfs、samba服务安装的步骤)。

    如果时间允许,最好找书本来学习,边看书边敲命令。因为书籍介绍比较系统,有利于了解全貌,再逐个知识点深入,做到胸有成竹。下面列一下需要学习的知识点。

    1、掌握常用命令。必须要学的命令不多,像查看文件、拷贝文件、创建文件、查找文件、显示日期、查看/修改IP,等等。这些常用命令只要使用次数多了,就能熟练掌握。具体的自行搜索。

    2、掌握软件安装步骤。一般linux系统发行版自带有安装工具,如unbutu,在联网情况下直接输入命令apt-get install tool-name,就能安装了。

    3、编译源码方式安装软件。有些工具提供源码需要自己进行编译(比如要在开发板上运行的程序,则无法通过apt-get来安装,需要交叉编译)。linux编译一般有三个步骤:

    配置:./configure

    编译:make

    安装:make install。

    这个知识点自行百度。

    4、了解linux文件系统、目录结构、设备文件。如根目录名称是“/”,配置文件一般位于/etc目录,运行程序一般位于/bin、/sbin、/usr/bin、/usr/sbin,等等。因为嵌入式涉及到根文件系统概念,因而需要对linux目录结构有了解。如果感兴趣,可以去搜索一下LFS。

    5、学习IO重定向、管道概念,学习并会写简单shell脚本。

    6、学习编辑器vi的简单使用(因为有些情况下只有这个编辑器可用)、编译器gcc用法、Makefile知识、gdb调试。(此项针对开发而言)

    推荐资源:

    笔者的主页和博客有大量linux系统使用、软件编译、Makefile,等等文章,欢迎前来围观。

    学习建议:

    1、看书、网络搜索

    2、学会man命令(这是linux内置的帮助命令,比如要了解cp命令的用法,则输入man cp)

    3、记录笔记

    二、应用层

    1、C/C++语言

    C/C++语言本身与具体平台相关不大,但必须结合具体环境平台才能展现其作用。比如,MFC使用C/C++,QT也使用C/C++,Linux内核中使用C,单片机使用C,等等。环境不同,其侧重点不同。在学校里学习C/C++语法,考完试,却没有结合实际项目编程,就有人纠结学了C/C++不懂能做什么。只有真正在某一领域使用了C语言,它才是一个可以看得见、摸得着的东西,而不再是抽象的。

     

    这里结合Linux系统,列举出一些要掌握、学习的知识点。

    1、linux系统编程基本概念:Makefile、gcc、gdb。

    2、文件IO操作。

    3、进程控制、进程间通信、多线程操作

    4、信号处理

    5、网络编程

    6、串口编程

     

    另外也列举C/C++语言的学习点:

    1、标准库

    输入输出(fprintf、sscanf)、文件操作(fopen、fclose)、字符类操作(isalpha、islower)、字符串操作(strcpy、strcmp、memcpy)、信号处理(signal)、日期时间(mktime、ctime)

    2、C++ STL

    向量vector、队列queue、栈stack、列表list。

    推荐网站:http://www.cplusplus.com/reference/

     

    下面列出一些我认为较好的书籍。每种类型的书籍应用场合不同,按需求学习。——不仅嵌入式Linux领域,其它很多领域同时需要C,因而要提高C技能。

    入门篇:

    《Linux C 编程一站式学习》

    《Linux C从入门到精通》

    《Linux C编程从初学到精通 》

    《Linux C编程实战》

    《嵌入式linux应用开发完全手册》 (该书对嵌入式Linux开发整体都有讲述,一书以看窥全貌,入门适用)

    linux网络编程篇:

    《UNIX网络编程》

    《UNIX环境高级编程》

    C/C++提高篇:

     

    《C陷阱与缺陷》

    《C专家编程》

    《C和指》

    《C++沉思录》

    《C/C++深层探索》

    《Effective C++中文版》

    《提高c++性能的编程技术》

    《0 bug:C/C++商用工程之道》 (这本书网络有一定争论,笔者认为有部分的确有可取之处,请辩证看待)

     

    学习路线:

    环境:安装虚拟机linux,配置好samba,有windows下用notepad++编写代码,然后在命令行使用gcc编译并运行。像ubuntu安装必要开发工具sudo apt-get install build-essential 这类的知识点本文就不涉及了。

    实践:首先了解linux下gcc编译基本概念,然后逐个知识点学习。以上每点均是一个知识块,需要手动写代码。建议在github上建立仓库,形成自己的代码库,方便日后使用。

    2、版本控制

    版本控制可以提高开发效率,目前很多公司使用svn或git进行代码管理,很多开源项目——包括kernel,都使用git来管理。对于不涉密的代码,推荐使用github托管,而不便公开的代码,可以在bitbucket或csdn上托管。养成保存代码的习惯很重要。笔者很多年前没有代码托管意识,一次电脑被偷,导致很多代码消失了,如今想找也想不回来了。

    版本控制学习成本不大,无非创建仓库、提交代码这些过程,结合日常编码练习,慢慢熟悉掌握即可。

     

    笔者录制了一个git教程,欢迎观看:

    http://edu.csdn.net/course/detail/4562

    3、脚本

    Linux系统的脚本语言有很多,使用场合也不同,主要目的是提高开发效率。比如:在shell脚本中完成代码的编译并拷贝到nfs共享目录(或tftp服务目录)。这样只需要执行脚本就完成多项工作,节省很多时间。

    4、界面开发

    界面开发不是笔者强项,就写一写笔者的经历。笔者接触过的界面开发有QT、SDL、MFC。这些都是作为工具而存在的,不是专门研究,都是工作需要时再去学习,边学习边实践。

    比如,做一个视频采集的软件,使用了SDL进行显示。

    比如,为了显示YUV格式的文件,使用MFC编写一个播放器。

    5、其它书籍推荐

    内功修炼篇:

    《程序员的自我修养——链接、装载与库》(偏底层的人建议看看)

    《高效程序员的45个习惯 敏捷开发修炼之道》

    《高质量程序设计指南》(建议看看,工作中编写代码一定要注意编码规范,否则维护难度太大)

    《Linux开发工具箱:项目开发的最有效途径》(对应英文版本《The Linux Programmer's Toolbox》,网络有资源)

    (注:入门级别书籍不建议购买,通过网络资源或去图书馆借书等手段来学习就行了。当然经济条件允许的除外)

    笔者这几年也积累一定的文章,欢迎阅读:http://blog.csdn.net/subfate/article/category/752115

    三、底层

    这里说的底层包括三大方面,这三大方面缺一不可。

    bootloader:作为上电运行的第一个程序,负责最原始的初始化操作,初始化芯片、初始化内存、初始化IO复用,读取内核代码并将控制权移交到内核,从而完成使命。

    kernel:提供基本的运行环境,提供外设操作控制接口。

    rootfs:向用词(应用层)提供基本操作环境,包括命令行、程序库等。

    1、bootloader(启动装载程序)

    嵌入式Linux常见的bootloader是u-boot,而X86领域中一般称为BIOS。u-boot的学习没有捷径,最好是在有ARM开发板情况下进行研究,通过打印信息的方法跟踪其流程。但是,看懂u-boot代码需要电路基本知识、芯片手册知识等等。——这些知识,同样适用于内核驱动的开发。

    首先要建立的是整体概念和认识。建议先把厂商提供的u-boot源码编译通过,并下载到开发板上看到正常结果后,再用串口打印信息搜索代码,以了解u-boot的代码流程。然后再慢慢研究。如果bootloader不是学习重点,在有一定概念前提下就可以跳过到内核驱动层了,不过就笔者经验来看,bootloader和内核关系十分密切且部分代码是相通的。

    一般初始化的代码是汇编代码,对于入门者而言,初学阶段不用追究,等有一定基础后再回头研究也不晚。

    笔者许多年前移植过u-boot,写了几篇文章,版本旧了一些,但对于学习而言还有有好处的:

    http://blog.csdn.net/subfate/article/category/751064

    笔者曾经研究过x86的开源bios,写了几篇文章,大家可以看看。虽然对于u-boot学习帮助不大,但可以了解笔者如何从零开始学习一个未知的知识。地址:http://blog.csdn.net/column/details/15826.html

    2、kernel(内核)

    内核是比较大的一块,涉及内容十分多。作为入门者,与u-boot类似,首先要建立的整体概念。先把厂商提供的内核源码编译通过,并下载到开发板上,串口会打印很多启动信息,这些启动信息能帮助我们学习内核,自己也可以在内核中打印语句,以了解其流程。

    每一个平台芯片不同,外设不同,内核均不同,需要进行移植。所谓的“移植”,就是找到合适的驱动,修改适应到该平台的过程。比如,某平台使用2个LCD屏,一个是3.5寸的,另一个是4.3寸的,这需要对内核进行修改。比如,这个平台使用nand flash是1GB的,另一个平台使用的是512MB的,也需要修改内核。其它如EEPROM、电源芯片、网卡,等等,均如此。

    内核知识点分2部分,一是kernel本身的知识点,如内存管理机制(MMU)、时间管理、同步机制,等等。二是外设驱动,如LED灯、GPIO、按键。

    初学者建议学习:

    1、了解内核编译的过程:配置内核、编译uImage。

    2、了解platform驱动模型(笔者文章有现成的模板,已经应用于很多个平台上)。

    3、了解一般外设驱动模型。建议从简单的LED、GPIO入门。

     

    高阶知识点:

    1、学习各种子系统,如MTD、USB、IIC、SPI、RTC、WDT。

    2、学习内核知识,如延时队列、时间管理,同步机制,等等。

    以下是笔者笔记关于内核专题的目录:

     

    推荐资源:

    《Linux设备驱动程序》第三版

    《Linux设备驱动开发详解》

    笔者开了一个专栏讲内核的,欢迎阅读:http://blog.csdn.net/column/details/15829.htm

     

    3、rootfs(根文件系统)

     

    一般情况下,开发板厂商会提供根文件系统,如果没有,则可以自己编译制作。一般嵌入式Linux使用busybox制作文件系统必要的程序、库、配置文件。因为busybox编译出来的内容体积小,节省空间,所以很多ARM开发板上都是用busybox的。另外还涉及到文件系统格式,像Yaffs2、ramfs、ext4、UBI,等等。所有这些知识点,请自行搜索学习。

    掌握程度:

    1、知道系统启动过程涉及到哪些脚本。知道上电启动时如何添加自己程序启动。

    2、了解各目录功能、存储哪些文件(如改IP在哪个配置文件,动态库在哪些目录)。

    四、其他知识

    1、电路原理图、datasheet

    作为底层开发人员来说,能看懂硬件原理图和datasheet是必要的一项技能。

    看懂硬件原理图,就可以知道这个系统上有什么器件,哪些器件有什么功能,如何连接(使用什么协议),提供什么接口。有了这些认知后,才会对系统有一个全局整体的认识掌握。对于开发人员来说绝对是有利的。

    看懂datasheet,才能知道如何访问器件,如何操作器件,了解其时序。

    另外,对于嵌入式经常接触到的如I2C协议,SPI协议等等的协议也要掌握。

     

    掌握程度:不需要像硬件专业同学那样学习数电、模电课程。但起码掌握上升沿、下降沿的概念,知道高电平、低电平概念,懂得看I2C协议的时序图。懂得如何找到datasheet中关键信息(寄存器说明、时序图)。

    学习路线:碎片时间多的人,建议在遇到不懂知识点时上网搜索学习。有条件的建议借书或买来学习。

     

    2、英文

    作为开发人员,英文是无涯逾越的坎,因为datasheet还有开发手册,几乎都是英文的。英文资料的特点是长句子多,而技术性术语多。初看英文的资料,可能进展很慢,但只要坚持下去,就会发现,英文手册也就那些术语而已。遇到不懂的术语,就记录下来。积累多了,阅读就慢慢顺畅了。除了术语外,语法难度,远低于高考、四级水平。

    值得说的是,国外原版书籍或手册,用词往往通俗易懂,但翻译成中文后,有的术语不对,有的句子顺序不对。这加大了阅读难度,也是造成技术书籍难懂的原因之一。

    个人经历:在某次旅途火车上,用手机看了一遍ONVIF协议手册,多年后再回看,基本已掌握。但目前ONVIF中文资料还是少。看懂英文资料,无疑有很大帮助。

    某次工作遇到网络问题,中文搜索无果,去各大英文论坛看,无意发现pause frame,继而看ieee802.3标准手册找权威说明,最后解决。这里英文资料帮了很大忙。

     

    3、其它

    其实很有许多其它知识,无法一一列举。

    本文提及的众多知识点,但绝不是在炫耀水平——因为那是笔者工作被逼去了解掌握的。但总而言这,在认清自己专注核心技能外,多掌握一些技能,总归有好处的。

    五、入门路线

    这里以偏重嵌入式Linux(ARM)驱动开发为例,给出一条入门的路线。

    1、买一款使用广泛、资料多的ARM开发板。因为使用的人多,你遇到的问题别人可能早就遇到并解决了,这样能省很多时间,并且提高自信心。可以到某宝上看看板子。因为是学习使用,最好便宜又适用的。

    2、使用vmware安装一个ubuntu系统。在vmware软件中设置物理桥接方式上网。在ubuntu设置好samba服务、nfs服务、tftp服务。

    3、首先自己动手亲自编译u-boot、kernel,烧写到板子上(注:有可能rootfs不提供源码,而是提供img镜像文件)。

    4、自己修改kernel,并编译busybox,烧写到板子,在板子挂载NFS,在虚拟机交叉编译一个Helloworld程序,并在板子上运行。

    5、根据兴趣,开始捣鼓:u-boot、kernel、应用层开发、QT开发。

    5、选择自己重点关注方面,继续研究。

    这个路线不一定要严格遵守时间轴。

    六、补充

    以上这些项,因不同人的基础而异。像硬件专业的同学,数电、模电和电路图已经掌握,就要加强C和Linux系统的学习。反之,计算机软件专业的同学,就要去学习硬件知识。等等。

    对于书籍,有的可能一下子无法理解,那是因为功力不到。有的可能觉得没有用处,那是因为还没有涉及此方面。比如,非计算专业的人看《编译原理》,《操作系统原理》,《计算机体系结构》,肯定是看不懂的,而且初学者也不必要看。又比如,嵌入式有的领域使用到H264编码、MPEG编码,802.11、CDMA,如果不是进入有关行业的,也不必学习。另外网上很多人写的嵌入式入门文章提到0.11内核版本、2.4内核版本的书,还有离散数字、算法导论的书,并不是都适用所有人。 所以大家一定要量体裁衣,有多大胃口吃多少饭,有多大头戴多大帽,根据自己已有的知识和所处的阶段进行选择。

    另外要说明的是,很多知识点是密不可分的,且界线是很模糊的。比如应用层和底层。因为有时出现问题,并不知道具体哪里的问题,这就需要站在比较高的层面(系统视野)看问题,才会快速定位并解决问题。建议以某一方面为核心点,另一方面做了解掌握。如果有能力,最好都学。

    本文所列举的项目条款,根据个人实际情况学习。建议逐步学习,各个击破。理论上知识点学得越多,越有利于看问题深度、广度的提高。

    一般情况下,嵌入式Linux没有速成。但可以达到入门速成,根据个人能力,我认为大约半个月~2个月即可,不过入门后就要不断学习和积累了,——这个积累,需要精力、时间的投入。

    在后续的系列文章中,笔者将介绍嵌入式Linux入门的一些方法和步骤,当然,不会详细到每个命令,每个驱动,只是根据笔者经验来描述,因此,更多的是经验的分享。

    PS:

    本文提到的服务设置这类操作,自行搜索了解。

    本文提到硬件、协议这类知识,自行搜索了解。

    文中提到书籍的机构与笔者无利益关系,不构成购买理由,请自行把控。

    李迟 2017.6.1 周四 (在远方顺祝我家大锤节日快乐,礼物上周已经网购回去了)

     

    展开全文
  • 嵌入式系统入门篇-1

    2021-03-02 14:43:56
    嵌入式系统入门篇笔记 1.嵌入式系统的定义(来自百度百科) 嵌入式系统是以应用为中心,以现代计算机技术为基础,能够根据用户需求(功能、可靠性、成本、体积、功耗、环境等)灵活裁剪软硬件模块的专用计算机系统。 2...

    嵌入式系统入门篇笔记-1

    芯片型号:STM32F407ZETx ,STM32F407ZETx采用内核是 ARM Cortex M4,哈佛架构

    1.嵌入式系统的定义(来自百度百科)

    嵌入式系统是以应用为中心,以现代计算机技术为基础,能够根据用户需求(功能、可靠性、成本、体积、功耗、环境等)灵活裁剪软硬件模块的专用计算机系统。

    2.嵌入式系统的体系结构

    冯诺依曼体系结构如图

    在这里插入图片描述
    哈佛架构如图
    在这里插入图片描述

    冯.诺伊曼把计算机系统分为如下几个部分:
    CPU(中央处理单元) = 算术逻辑单元(运算器) + 控制电路
    存储器 Memory:
    ·ROM: Read Only Memory 只读存储器
    ·RAM: Random Access Memory 随机访问存储器 “R/W”
    输入输出设备

    哈佛架构(Harvard Architecture)
    是一种将程序存储和数据存储分开的存储器结构,数据存储器与程序存储器采用不同的总线。
    C51,ARM9之后嵌入式系统芯片

    3.嵌入式系统的组成

    硬件:芯片(CPU+总线+外设控制器)、外围电路……
    STM32F407ZETx
    软件bootloader 引导程序(作用:引导其他系统软件运行)在上电的时候,大多数硬件是不能正常工作的,并且CPU等少数硬件,只能在比较低的频率下工作。
    bootloader的作用:
    (1) 初始化必要的硬件
    (2) 把系统软件(如:OS)引导到内存中运行
    OS: Operator System 操作系统 (OS是用来管理和分配(硬件)资源的系统软件。)
    现代操作系统一个特征是:并发。 “多任务”所有任务的执行,都需要CPU,但是CPU的数量非常有限。
    调度:决定哪一个任务获取CPU的执行权。
    调度策略
    (1)分时策略 -> 分时系统:分时间片执行
    windows 塞班 ios linux unix android ubuntu RedHat
    (2)实时策略 -> 实时系统 RTOS: Real Time OS 实时系统每次取优先级最高的那个任务执行,直到这个任务结束、或者是它主动放弃CPU、或者有更高优先级的任务抢占它。
    ucos freeRTOS vxworks …
    应用程序(包括文件系统)……

    4.各组件间的通信

    • 通信方式: 通信双方(发送方,接收方)

      • 全双工:同一时刻一方即可以发送数据给对方,又可以从对方接收数据。
      • 半双工:同一时刻一方只能发送数据给对方,或者是从对方接收数据。下一个时刻,可以改变。
      • 单工:任意时刻 一方只能发送数据给对方,或者是从对方接收数据。
        总线bus:计算机系统内部各组件之间是通过“总线”的来通信的。
    • 总线两个特点:
      (1) 多个部件可以同时从总线上接收相同的信息 -> 广播式
      (2) 任意时刻只能有一个设备向总线发送信息 -> 系统瓶颈
      (总线协议规定发送规则)

    • 总线: 按功能分

      • 数据总线(DB): 双向,宽度差别8bits/16bits/32bits
      • 地址总线(AB): 单向,CPU发地址,宽度与寻址空间有关 24bit==>16MB
      • 控制总线(CB): 命令和状态

      按位置分

      • 片内总线
      • 系统总线
      • 通信总线(I/O总线)

    5.存储器的逻辑结构

    在这里插入图片描述

    双地址译码存储结构
    如:存储器(内存)64*64字节存储矩阵:字节编码,需要12 bits

    6.ARM Cortex M4体系结构

    1.Cortex M4总线接口:哈佛架构,三套总线
    (1) Icode总线,用于访问代码空间的指令instruction, 32bits 访问的空间为: 0x0000 0000 ~ 0x1FFF FFFF (512M). 每次取4字节指令,只读.
    (2) Dcode总线,用于访问代码空间的数据data, 32bits访问的空间为: 0x0000 0000 ~ 0x1FFF FFFF(512M)。非对齐的访问会被总线分割成几个对齐的访问。“4字节对齐”:地址必须为4倍数(后两位为0,会做其它用途)。
    从最底层来讲: 4字节对齐,CPU写出的地址必须为4的倍数。
    如果底层硬件(体系结构)规定是4字节对齐,相应的编译器也会考虑到对齐的问题.否则效率会变低!
    (3) System 总线,用于访问其他系统空间。如: 各硬件控制器,GPIO……。访问空间为 0x2000 0000 ~ 0xDFFF FFFF 和 0XE010 0000 ~ 0xFFFF FFFF。非对齐的访问会被总线分割成几个对齐的访问。I/O总线,用于访问芯片上的各外设寄存器的地址空间的。

    7.Cortex M4工作状态(处理器状态)

    • ARM公司设计的CPU,可以支持两种指令集:
      • ARM指令集:32bits,功能比较强大,通用
      • Thumb指令集:
        • thumb 16bits, 功能也强大(Cortem M4只支持Thumb指令)
        • thumb-2 32bits,功能强大,增加了不少专用的DSP指令

    8.Cortex M4寄存器

    • 通用寄存器: 没有特殊用途
      • R0~R7: 所有thumb thumb-2都可以访问
      • R8~R12: 只有少量的thumb指令可以访问,thumb-2都可以访问
    • 专用寄存器: 有专门的用途(R13 R14 R15 xPSR)
      • R13(SP): 栈顶指针寄存器(Stack Pointer)保存堆栈的栈顶地址。
        堆栈(Stack): 是用“栈的思想”来管理的一段内存。
        “栈的思想”:先进后出
        堆栈的作用:为了支持过程调用(函数)。1)“现场保护”;2)函数的具体功能的代码;3)“现场恢复”。
        过程调用(跳转):一个过程还没有结束,就去调用另外一个过程。所有指令的操作数和结果都需要在寄存器中,CPU才能访问一个过程的一些中间结果(保存在寄存器中的),如果一个过程,去调用另外一段代码(过程调用),另外的那段代码势必也要修改寄存器,如果另外那段代码不事先保存寄存器里面的内容,在代码结束,返回到前面的那个过程时,结果就会不对。
        过程调用(函数):
        “现场保护”:把寄存器里面的内容保存到内存中去 。 下一条指令地址保存到 R14 —入栈
        “现场恢复”:把原先保存的内容还原到相应的寄存器中去。 R14—出栈 R14----R15
        这个过程,正好是 “先进后出”

        小贴士: 堆栈有四种类型:空递增、空递减、满递增和满递减。(在该门课程中的堆栈是空递减)

        思考:(1)在C语言完成一个功能,我们可以定义一个宏,也可以定义 成一个函数,请问宏与函数有什么区别?
        答:函数有额外的开销(现场保护…现场恢复),但是宏没有。
        (2)C/C++中,为什么需要把一个函数声明成inline?
        答:inline内联函数:函数定义前加inline关键字,不会有额外开销,把被调用的部分复制到调用它的地方。

        小贴士: 所有支持过程调用的语言,都需要用到栈。
        Cortex M4有两个堆栈,双堆栈(MSP 主堆栈指针、PSP 进程堆栈指针)
        双堆栈的用处:为了支持操作系统。把操作系统用的堆栈和用户进程用的堆栈分开。

      • R14(LR): Linked Register 链接寄存器
        在执行过程调用的指令的时候,我们需要保存该指令的下一条指针的地址,因为这个地址,就是需要返回的地址。LR寄存器,就是用来保存过程调用调用的返回地址。

      • R15(PC): Program Counter 程序计数器,保存下一条要执行的指令的地址。PC会在取指后,会自动增加指令所占的bits位数。
        在ARM Cortex M4, PC + 4 在有“指令流水线”情况下,PC的值会有所不同。
        程序实现的跳转,就是往PC中赋一个跳转的地址(跳转就是不按顺序执行)。

      • xPSR: Program Status Register程序状态寄存器。
        程序状态寄存器:保存程序运行过程中的一些状态,这些要保存的状态,分为三类:

        • 应用状态寄存器 APSR: 计算结果的标志 N Z C V Q
        • 中断状态寄存器 IPSR: 中断的编号 Exception Number 8bits
        • 执行状态寄存器 EPSR: 执行状态,如: Thumb/ARM
          组合一个32bits的xPSR,如图:
          在这里插入图片描述
          N Z C V Q 我们每一条指令的执行都可以影响这些状态标志位。
          N: 负数标志。 Negative is set o bit 31 of the result(标志根据运算结果来设置)
          xPSR.N < Ret[31] 最高位是符号位 1 -> 负数, 0 -> 非负数
          如果 xPSR.N==1,表示上一条指令的操作结果为负数。

        N什么什么情况下会置位呢?
        答:如果一条指令,影响状态标志位(通常是+S的指令,如MOVS),指令可以不影响状态标志位,也可以设置为影响标志位。
        如:MOV R0, #3 ; ->不影响状态标志位,不管这条指令的执行结果如何,xPSR不变。
        MOVS R0, #3; ->影响状态标志位,xPSR.N <- 结果寄存器[31]
        MOVS R0, #3 R0[31] -> xSPR.N == 0

        Z : Zero 。零标志。结果所有bit位都为0,则xPSR.Z== 1否则xPSR.Z== 0,前提也是指令结果影响状态标志。
        如:MOVS R0, #0; -> xPSR.Z== 1
        MOVS R1, #4 ; -> xPSR.Z== 0
        MOV R2, #0 ;没加S,表示指令的执行,不影响状态寄存器 -> xPSR.Z值不变。
        C: Carry 借位或进位标志。
        进位: 在做加法运算时,产生了进位。则C== 1,否则 C== 0
        借位: 在做减法运算时,没产生借位。则C== 1,否则 C== 0
        ADC, ADD, CMN 加法。如果产生了进位,则C== 1,否则 C== 0
        SBC, SUB, CMP 减法。如果生生了借位,则C== 0,否则 C== 1
        如:MOV R0, #2
        MOV R1, #3
        SUBS R2, R0, R1; R0 - R1 -> R2
        R0 - R1 产生借位。 C== 0
        xPSR.C== 0=> R0 < R1
        --------
        SUBS R3, R0, R1
        R0 - R1 -> R3
        R0 - R1没产生借位,C== 1
        xPSR.C== 1,R0 >= R1
        -------
        CMP R0, R1
        xPSR.C== 0 => R0 < R1
        CMP R1, R0
        xPSR.C== 1 => R0 >= R1
        小贴士1: CMP是比较操作码,它会把两个操作数做减法看标志位从而看哪个数更小。
        小贴士2: 在计算中要注意数在机器中是用补码表示的,正数的补码是它自己,负数的补码=原码取反+1。如-9,9的原码为00001001,取反为11110110,加一为11110111,故-9的补码为11110111.
        小贴士3: 上述关于标志位结论都在机器上验证。

        以下指令执行后对应的标志位数值
        MOVS R0,#-2 //N=1,Z=0,C=0(R0=0xffff fffe)
        MOVS R1,#2 //N=0,Z=0,C=0(R1=0x0000 0002)
        ADDS R2,R0,R1 //N=0,Z=1,C=1
        SUBS R3,R0,R1 //N=1,Z=0,C=1(0xffff fffe-0x2000 0000)
        SUBS R4,R1,R0 //N=0,Z=0,C=0(0x0000 0002-0xffff fffe)
        CMP R0,R1 //N=1,Z=0,C=1
        CMP R1,R0 //N=0,Z=0,C=0

        V: oVerflow 溢出标志,反映有符号数做加减运算所得结果是否溢出,如果运算结果超过当前运算位数所能表示的范围,则溢出 xPSR.V = 1, 否则为0. 在有符号的运算中,进位(借位,C)与溢出是两个完全不同的概念。

        CASE 1: 有进位,结果溢出
        1111 1111 1111 1111 1111 1111 1111 1111 0xffff ffff(-1)
        +1000 0000 0000 0000 0000 0000 0000 0000 0x8000 0000(-2^31)
        -------------------------------------------------------------------------
        1 0111 1111 1111 1111 1111 1111 1111 1111 +2^31-1
        溢出:负数 + 负数 = 正数(结果溢出)
        C30 = 0
        C31 = 1
        代码测试
        MOVS R0,#0xffffffff
        MOVS R1,#0x80000000
        ADDS R2,R0,R1
        结果N=0,Z=0,C=1,V=1
        CASE 2: 有进位,结果未溢出
        0111 1111 1111 1111 1111 1111 1111 1111 (2^31-1)
        +1111 1111 1111 1111 1111 1111 1111 1111 (-1)
        ------------------------------------------------------------------
        1 0111 1111 1111 1111 1111 1111 1111 1110 (2^31-2)
        正数+ 负数 = 正数(结果未溢出)
        C30 = 1
        C31 = 1
        代码测试:
        MOVS R0,#0x7fffffff
        MOVS R1,#-1
        ADDS R2,R0,R1
        结果N=0,Z=0,C=1,V=0
        CASE 3: 无进位,结果溢出
        0111 1111 1111 1111 1111 1111 1111 1111 (2^31-1)
        +0000 0000 0000 0000 0000 0000 0000 0001 (1)
        -------------------------------------------------------------------
        1000 0000 0000 0000 0000 0000 0000 0000 (-2^31)
        正数+ 正数 = 负数(结果溢出)
        C30 = 1
        C31 = 0
        代码测试:
        MOVS R0,#0x7fffffff
        MOVS R1,#1
        ADDS R2,R0,R1
        结果N=1,Z=0,C=0,V=1
        CASE 4: 无进位,结果未溢出
        1111 1111 1111 1111 1111 1111 1111 1110 (-2)
        +0000 0000 0000 0000 0000 0000 0000 0001 (1)
        -------------------------------------------------------------------
        1111 1111 1111 1111 1111 1111 1111 1111 (-1)
        负数+ 正数 = 负数(结果未溢出)
        C30 = 0
        C31 = 0
        代码测试:
        MOVS R0,#0xfffffffe
        MOVS R1,#1
        ADDS R2,R0,R1
        结果N=1,Z=0,C=0,V=0

        Cn表示最高位的进位(或借位)标志
        Cn-1表示次高位的进位(或借位)标志
        综上所述:V = Cn 异或 Cn-1

        Q: 饱和标志
        饱和计算: 通过将数据强制置为最大(或最小)允许值,减小了数据畸变,当然畸变仍然存在,不过若数据没有超过最大允许范围太多,就不会有太大的问题。

        8bits无符号的加法:
        普通计算: 11111111 + 1 = 0
        11111111
        +00000001
        -----------------
        100000000
        饱和计算:11111111 + 1 = 11111111
        例子: 0111111111…11 => 0X7FFF FFFF
        1000000000…00 => - (2^31)
        ADD 普通加法
        QADD 将两上有符号的32bits相加后,进行饱和操作
        MOV R0, #0x7FFFFFFF
        MOV R1, #1
        ADD R2, R0, R1
        QADD R3, R0,R1

        T : xPSR[24]表示处理器当前执行的状态。(工作状态/处理器状态)
        ARM状态 xPSR.T== 0
        Thumb状态 xPST.T== 1

        IT:IF-THEN instruction status bit for conditional execution IF-THEN 位,它们是if-then指令的执行状态位(最多4条)
        例如:ITTT 三条then

        if (R0 > R1) // CMP R0,R1 GT:大于
        {
        r2 = 2 MOVGT R2, #2
        r3 = 3 MOVGT R3, #3
        r4 = 4 MOVGT R4, #4
        }
        ITE (下面汇编指令就相当于if-then-else语句)
        CMP R0,R1(比较R0,R1)
        MOVGT R2,#2(如果R0>R1,将2放进寄存器R2)
        MOVLE R3,#3(如果R0<R1,将3放进寄存器R3)
        上面指令执行了第24行指令,贴个图~~在这里插入图片描述

        ICI : Interruptible-Continuable Instrument 可中断-可继续指令位
        与IT共用位置,如果执行LDM/STM操作(对内存进行批量拷贝)时,数据没有操作完时,产生一个中断,中断的优先级很高,必须要打断这条指令的执行,这种情况,就需要记录被打断的寄存器的编号,在中断响应之后,处理器返回由该位指向的寄存器,并恢复操作,继续执行拷贝。

      • 中断屏蔽寄存器:中断 异常

        • PRIMASK[0] 片上外设的总中断开关
          1 屏蔽所有的片上外设中断
          0 响应所有外设的中断

        • FAULTMASK[0] 系统错误异常的中断总开关
          1 屏蔽所有异常
          0 响应所有异常

        • BASEPRI 为使中断屏蔽更加灵活,该寄存器根据中断优先级来屏蔽中断或异常。当被设置为一个非0的数值时,它就会屏蔽所有相同或更低优先级的异常(包括中断),则更高优先级的中断或异常还会被响应。每一个异常或中断,都会有一个优先级,中断数值越低优先级越高(一般从2开始往上设值)。

      • CONTROL寄存器(初始值0x00):用来控制选择哪个堆栈(主堆栈/进程堆栈),选择线程模式的访问等级(特权等级/非特权等级),特权等级可以访问所有;非特权等级只能有限访问。
        CONTROL[0] :线程模式的访问等级
        1 非特权等级
        0 特权等级
        CONTROL[1] :堆栈的选择
        1 进程堆栈 PSP
        0 主堆栈 MSP(目前只用到这个)

    9.Cortex M4工作模式

    “模式”: 不同环境,不同的角色

    ARM cortex M4有两种工作模式:
    Thread Mode: 线程模式(用户程序该干嘛干嘛)
    Handler Mode: 处理模式(异常中断模式)

    异常/中断: 打断CPU指令执行顺序的事件,称为中断

    思考:为什么要支持两种模式呢? 为什么不只用一种模式呢? Thread Mode
    如果只用一种模式,thread mode,为了响应一些外部事件(比如说,用户是否按下某个按键?):
    轮询:轮流询问。 通过轮询,CPU也可能 响应外部事件,但是轮询天生就有缺陷:
    (1) 浪费CPU
    (2) 占用总线, Bus is always busy.
    (3) 轮询有一个时间差,轮询的时间间隔。不及时!!!

    在CPU内部设计一个 “中断模式”:为了提高效率和响应速度。

    Handler Mode :中断模式,当一些比较重要的事件,产生时,CPU中止正在做的事情,切换到Handler Mode下去执行,此时 “特权等级”中断处理完成后,再返回到断点处,继续Thread Mode运行。
    Thread Mode:线程模式。
    特权等级 : 可以跑一些如OS的代码
    非特权等级: 可以跑一些如 "用户态"的代码 在这里插入图片描述
    小贴士: 特权等级 -> 非特权等级,但是:非特权等级不可以切换到特权事件,除非产生“中断”。

    展开全文
  • 嵌入式如何入门

    2014-12-16 23:32:43
     1、学习linux根据我在论坛的了解,我选择学习嵌入式linux,刚好我们学校也重视嵌入式linux,实验室课程安排都是关于嵌入式linux方面,天时地利!这里我把学习linux的经验和教训说说。    可以这样说,...

    这个题目很大,给人一种感觉我好像很成功,其实不然。实际上自己水平不高,甚至很低,但是做过了一些曲折的学习道路,同时把自己真实的学习历程表达出来,希望对后来者有借鉴的意义,甚幸!
     
      工作三年、几成废人!
     
       我2000年毕业于华中地区的一个理工科大学,专业是机械电子,我当时已经签了一家内陆某个省级机关工作,家里八辈是农民,并且很偏远,能够进入这样的 地方是祖坟有风水。但在毕业前夕有个进入it的机会,我本想进去的,家里人极力反对,阻力可想而知。同时要交4000元的违约金,对我来说是天文数字。大 学里的费用很多是借的,几乎将近一半的费用是在大学勤工俭学挣的,为了省钱,高中一个学期回家一次,大学一年回去一次。并且我个人也有特殊的人生背景(悲 景更确切),这里不多说了,写十篇也写不完,同时偏离主题。这样我就参加了工作。一张报纸一杯茶的日子,几乎下班后有种很空虚和恐慌的感觉。在工作中虽然 是与自己专业有点关系,但是很少。专业几乎荒废。我自己也思考,如果再不出去,自己将会成废人,只好让国家养了。两年后决定出去,但是几成废人,谁要呢, 只好到学校去镀金。这是中国教育和社会的悲哀!
     
      至于专业就改为计算机方面,听说好找工作,我说实话不是很对计算机特别感兴趣,生存第一需要。不要笑我,哈哈!
     
      考研成绩出来,超过了国家线几十分。那个方向要两个,我第三,但是那年非碘,不面试就按分数来排,自然我落选了。其实给我面试机会也不一定要我,哈哈,自己几斤几两很清楚。
     
      最后调剂到另外一个学校,交钱,咬咬牙,交吧!现在仍然债台高筑!
     
      进入学校前夕为什么要把这段列出,看后就知道了。
     
       单位有网络,经常上网查些英语资料,在那里唯独英语没有丢很多。于是我就在网上查资料,学什么好呢,最后确定学嵌入式把,听说跟硬件相对比较紧密!而我 在大学里多少学习了数字电路,单片机等,所以多少也有所利用,不会真的一无所知。当然在这之前也自学过数据结构,计算机组成原理等。C 语言在大学就学了。哈哈这就是我的家底。
     
      我知道自己的基础差,于是我就拿操作系统,数据库、数据结构、c++来看,机关有这个好处,空余时间多,于是平常就看书,很痛苦,没有人请教。
     
      另外就上网到论坛上去,我就到各个专业的技术论坛,其实是电子论坛和嵌入式论坛。我几乎没有发帖,几乎把几个大型的出名的论坛的帖子翻遍了,虽然有很多重复的,我才知道嵌入式是个什么东东。这些帖子对我以后的学习产生了极大的影响。
     
      最关键两点:1、嵌入式是什么?
     
      2、嵌入式需要哪些知识?
     
       知道了这两点,好办!我就开始规划学习路线。计算机的基本理论不能丢,于是重点看组成原理,数据机构,操作系统、c++.同时论坛上了解到,实时操作系 统ucos是一个很好的嵌入式操作系统,对初学者很好。于是我就买了一本书,但是代码在电脑里调不通,网上也有很多相同的问题,我就看书,分析代码,一遍 不行就两遍,三遍,这样才看了入了门,才知道什么是进程。原来看操作系统书时,根本就不知道进程是个什么东西。在这段时间掌握的东西不多,但是,对我以后 的影响很大,我想起了大学时一个同学跟我说过了一句话:大学里最重要的不是学到了什么,最重要的是学会怎么学!大概是这个意思。
     
      进入我的避难所对我来讲,再次进入大学不再是大学,而是避难所。希望这次进入给我喘气和养精蓄锐的机会和时间。我是这样认为和实践的。
     
      在学校我有三件事:上课,上图书馆,上网。
     
       对于上课,学校开了很多课程,非常好,很多是名人名师讲解,于是很多同学都想学,都去听。我也考虑过,最后放弃。我是这样认为的,时间是有限的,什么都 想学,什么都学不成。于是我把我自己学的课进行了分化,一般的课程通过就行,重要的一定好好学。我希望不要什么争论学习课程多和少的问题,这仅仅是我的看 法。所以我的成绩应该是很差的。分数低。好在后来的单位没有要我的成绩单,否则就惨。
     
      我个人感觉是上图书馆的效率比在寝室里高多了,这是我的经验。
     
      上网,我给自己定了规矩:不玩游戏,不灌水,少看电影!因为时间对我来说太少和宝贵了,我没有资格和资本来浪费这些。上网我就在几个重要的专业技术网站上逛,下载技术资料。 
      有人会问,您下了那么多资料,怎么看的完和消化的了呢?
     
      我是这样对待这个问题的:1、 网上资料比较零散,不系统,但是如果把差不多的东西收集起来看就相对完整了,(嵌入式的图书就是这两年特别多,特别是2004年,简直是向外涌!2003年想买本嵌入式,特别是嵌入式linux的不多。)
     
      2、 对于像我这种入门的来说,很多看不懂,没关系,反复看,我个人对学习方法的一个总结是:重复是最好的老师!
     
      3、 即使有的用不上,也可以收集以后用的上时查阅。
     但是我并非什么都要,目前我的技术路线是嵌入式linux,所以像wince之类基本上不收集。
     
      总之,我在学校里我充分利用时间来学习,我看到一些同学整天的挂在网上打游戏,发些无关痛痒的帖子,浪费时间呀!我真的很痛心!
     
      学习嵌入式在这里我把它单独列出,文章有点紊乱,但是内容希望有益。
     
      1、学习linux根据我在论坛的了解,我选择学习嵌入式linux,刚好我们学校也重视嵌入式linux,从实验室到课程安排都是关于嵌入式linux方面,天时地利!这里我把学习linux的经验和教训说说。
     
       可以这样说,在论坛里说道学习linux差不多就学习linux内核。于是我电脑里安装了linux就开始看linux内核方面的书了。我记得来学校以 前就买到一本陈莉君的讲linux内核的第一版,现在有第二版了。我就开始看那本说,大家说linux内核情景分析不错,我就买了上下册,后来又买了 《深入理解linux内核》,最后猜蛄嗣虏俚摹肚度胧较低场芬彩欠治鰈inux内核代码的,主要讲arm相关的。
     
      看内核期间是个 非常痛苦的过程,看情景分析有种在森林中找出路,其间我组织了一些同学学习内核,几乎没有几个能坚持下来的。我认为我是坚持下来了。情景分析在看第一、第 二遍是几乎没有摸到门道,我分析有三个方面的原因:1、自己的基础差,这是最关键的。2、内核本身很难。3、没有交流和高人指点。到了第三遍时我才摸到 门,才差不多知道个linux的大概脉络,很多细节也是稀里糊涂。
     
      学习linux总结,这里声明一下,我指的嵌入式主要是偏向软件的嵌入式。学习嵌入式的重点和难点关键在操作系统,如果没有掌握操作系统,我认为很难把握一个嵌入式系统。即使在做嵌入式开发中,作应有层的开发几乎可以不知道操作系统也可以开发,我认为那是浮在表面的。很难深入和提高自己的层次。声明:一孔之见!不可深究!
     
       在学习linux内核过程中犯了一个极其严重路线错误:对linux几乎不懂就开始学习内核。我个人推荐一个学习路线是:使用linux—〉linux系统编程开发——〉驱动开发和分析linux内核。而我差不多相反,实际上你不会使用linux也可以学习内核,但是如果你懂了这些东西学习更有效率。
     
       关于要不要学习内核的问题,我的回答如下:不一定。如果你是喜欢钻研的那你进入内核会满足你的欲望。同时对你以后的嵌入式系统的开发有很好的影响。如果 你想从事嵌入式linux系统开发,最好对内核有所了解。如果仅仅是做应用开发没有必要。我打个比喻:c、c++、java等语言是武林中的某个武林派别 的话,如什么拳法,什么刀法等,那么linux 内核应该是一个人的内功的反应。
     
      怎么开始学linux内核:最好有三件宝物:《深入理解linux内核》《情景分析》和源代码。
     
       先看《深》,那主要讲原理,好像市场上有本讲原理性并且更浅,《linux内核设计与实现》听说不错。如果没有学习操作系统的,像我这样的,最好先看看 操作系统原理的书。看了几遍后,就看情景分析,最好对着《深》看。两本交*看,《深》是纲,《情》是目。最后深入代码。
     
      2、学习嵌 入式linux学习嵌入式,我认为两个重点,cpu和操作系统,目前市场是比较流行arm,所以推荐大家学习arm.操作系统很多,我个人对开始学习的人,特别不是计算机专业的,推荐学习ucos.那是开源的,同时很小。学习很好。为什么选linux,我不想讲太多,网上这方面的太多,但是我在工作中发 现,做linux的技术路线很难,在windows几乎不会有的问题,在linux开发中几乎遍地陷阱。一掉进去划很长时间出来,一旦解决自己又长进了! 相对来说开发周期长,难度大。现在资料也逐渐丰富起来,难度也降低了些!
     
      至于怎么学习,这是他的特色地方,必须有块开发板,我是同学里最早买学习板的,虽然化钱,我认为值。对我实习和工作产生了很大的影响。
     
       如果没有开发板,那是纸上谈兵。有人说,那要1000-2000亚,的确是,兄弟,看长远的,对您的职业和发展那点钱不算什么!有的人说我站着说话不腰 痛,好吧,钱这东西对我影响很大,我在大学里扫厕所,扫的不错,奖5元/月。兄弟你有过吗?我认为教育投资是效益最有保障的!我实习拿3k,很多同学拿 1-2k,当然比我高的也有。虽然我现在没有毕业,但一家公司就签了。从事目前流行的高档的消费电子的研发。对于我两年前一无所知的我,应该有质的变化, 我感谢学校收了我这个废品。当然我也非常的努力。说这么多并不是要炫耀我什么,实际上根本不值得炫耀,虽然现在工作环境和待遇比较满意,但是,我发现我很 差,特别是代码能力,我希望平常大家少玩游戏,多编程。编程才是硬道理!3、 学习板和培训你可以不接受培训,但是不能不买开发板。如果你想学习嵌入式一定要买块学习板,最好买块arm9的,贵些也值。可以跑高级操作系统。这 个不要什么品牌公司的,一般不会出什么问题,市场上的板子一般是三星的2410,基本上是抄的。如果是做产品那要注意些。一般的公司一般要2000,加 lcd要3000甚至更多。我接触到有的板只要1200,加lcd也就2000,差别比较大,我认为学习都够啦。
     
      对于培训,如果有 条件最好参加,主要是嵌入式相对别的不同,自己摸索很费时,如果有高手指点非常的好,进步快。特别是认识做这些的朋友。我接受过培训,认识个朋友。在以后 的工作中帮我很多,在这里谢谢他!我记得哈佛的一个MBA的学生这样说,大意是:在哈佛学到什么不重要,最重要的是这些未来各大公司的高级管理人员是我的同学!真是有远见!
     
      目前市场是培训比较贵,一个星期两三千,真正算起来也要,那些讲师待遇绝对不会低。但是有个致命的问题是连续上课,一连几天,效果不佳。我希望社会上多出些1000元左右,并且时间长些,如一个月,一周一到两次课。如果没人做,我来做,哈哈!
     
       没有想到,一下写了这么多,其实还想写的,比如在中科院的一位老兄是怎样学习linux内核和看书的,真的很感动。他的为人我很钦佩。也想介绍毛德操的 《嵌入式系统》那本书,对学习arm linux的很好,也想介绍实习和工作的东西,太长了,耽误大家时间。我也不想检查里面的错别字了,很多!就写到这里吧。

    展开全文
  • 嵌入式linux入门笔记

    2019-10-15 22:13:50
    一开始假设是裸板,首先要用jtag把uboot烧nor flash,完成后拔掉jtag,然后板子nor flash,刚开始启动时马上按空格键进入uboot选择菜单,菜单中可以选择烧写普通bin文件Nand Flash,也可以选择烧写内核或根...
  • 本人大学学的是电子信息科学与技术专业,其实这个专业和嵌入式没有多大的关系,要说有关系就是简单的讲了下C语言语法,学完之后还不知道什么是C语言,只记住了,char,int,string等占几个字节,if, for, while循环...
  • 粤嵌上课要准备粤嵌上课要准备学习方面的 1一直用同一交叉编译链就好了 2使用64位的linux系统的同学安装兼容32位软件 3更换虚拟机源etcaptsourceslist 4安装的好用的linux软件 5安装putty ...12放弃tftp
  • 发现放CSDN之后排版全乱套了。。已经在我自己的站点重新排版: Github · 目录 导 航 1.引言 1.1.编写目的 1.2.阅读范围 1.3.声明 1.4.缩写词/名词解释 1.5.参考资料 2....
  • STM32 嵌入式学习入门(0)——C语言基础复习

    万次阅读 多人点赞 2018-02-11 23:02:13
     主要介绍了嵌入式编程中几个常用,但软件编程中用得不是很多的C语言知识。包括位操作、条件编译、结构体和结构体指针、typedef声明类型、以及extern变量声明、static关键字等内容。  本文并没有将相关C语言知识...
  • 嵌入式OS入门笔记-以RTX为案例:五.简单的时间管理 绕过排程器,简单介绍了进程间协调占用CPU的办法。
  • 现在还清清楚楚的记得装ubount的样子,完全就是不知道该怎么操作,ping不上之类的,从入门到放弃。 我其实是万万没想到在多年后我还会重新在当年跌倒的地方爬起来,原因很简单,被生活逼得没办法。这次我成功的熬过...
  • 位操作符在嵌入式开发中最为常用,如通过位运算符进行运算操作、对寄存器中进行操作。 六种常用的位操作符:位与( & );位或( | );位异或( ^ );左移操作符( > );求反( ~ )。 举例: 位与(&):基本用途...
  • 嵌入式OS入门笔记-以RTX为案例:八.RTX的进程间通讯(二) 介绍了RTX的信号量和邮箱机制。分析了信号量和互斥锁的区别。
  • 一、嵌入式系统的知识体系 嵌入式系统的应用范围...这些应用可以看出,要完成一个以MCU为核心的嵌入式系统应用产品设计,需要硬件、软件及行业领域相关知识。 硬件:主要有MCU的硬件最小系统、输入/输出外围...
  • STM32 IIC实验讲解,从入门到放弃

    千次阅读 多人点赞 2021-02-13 10:39:10
    STM32 IIC实验讲解,从入门到放弃。 文章目录STM32 IIC实验讲解,从入门到放弃。前言一、IICIIC是什么?IIC协议二、代码部分IIC底层代码分析总结 前言 本文参考了网上的博文,并加以归纳总结,帮助新手从入门到放弃...
  • 此文是本人在知乎上看的,觉得很好就分享出来了,并不是本人原创 转自:https://www.zhihu.com/question/47881392 ...商业转载请联系作者获得授权,非商业转载请注明出处。 ...嵌入式Linux+And...
  • 声明:本文内容为本人学习嵌入式linux所遇问题后,将自己所理解的注意事项作出总结,以便日后学习,如有错误,请大神能予以指出,小弟不胜感激! 环境:VMware-workstation-full-10.0.4-2249910 和 ...
  • 刚才一个在校生问我关于嵌入式入门学习之类的话题,说实在话,这种问题我回答的太多了,以前在CSDN,郁闷的是没有整理成一篇文章,现在当即回答这位同学的问题。 尊敬的gooogleman,在基于ARM--WINCE嵌入式入门阶段...
  • 学Python方法用错,直接从入门到放弃你开始学习编程的那一刻起,就注定了以后所要走的路—编程学习者开始,依次经历实习生、程序员、软件工程师、架构师、CTO等职位的磨砺;当你站在职位顶峰的位置蓦然回首时...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 4,728
精华内容 1,891
关键字:

嵌入式从入门到放弃