精华内容
下载资源
问答
  • 近几年,嵌入式系统产品渐渐完善,并在全世界各行业得到广泛应用。2004年,全球嵌入式系统产品的产值已达2000亿美元,国内嵌入式软件的产值也达到600亿人民币。据预测,随着Internet的迅速发展和廉价微处理器的出现...
  • 《ARM嵌入式Linux系统开发从入门到精通》+光盘资料
  • BECKHOFF嵌入式PC从入门到精通V2.03.pdf
  • ARM嵌入式Linux系统开发从入门到精通
  • BECKHOFF嵌入式PC从入门到精通V26
  • 倍福系统概述、编程软件、常用功能及编程技巧、TwinCAT
  • 本书基于Linux2.6内核讲述了Linux嵌入式驱动程序开发的知识,全书内容涵盖了Linux2.6下的三类驱动设备,包括Linux下字符设备、块设备、网络设备的开发技术。具体内容包括Linux驱动开发入门基础知识,Linux操作系统下...
  • 嵌入式系统移植-01嵌入式基本概念,嵌入式开发环境搭建,目标机搭建,TFTP服务搭建,NFS服务搭建 系统移植概述及环境搭建 通用嵌入式系统软件组成部分 无os嵌入式系统组成图 有os嵌入式系统组成图 Linux 在...

     

    目录

     

    01嵌入式基本概念,嵌入式开发环境搭建,目标机搭建,TFTP服务搭建,NFS服务搭建

    1.系统移植概述及环境搭建

    1.通用嵌入式系统软件组成部分

    2.Linux 在嵌入式中应用的条件与前景

    3.嵌入式Linux内核结构​

    4.Android系统

    2.嵌入式开发环境搭建

    1.嵌入式Linux交叉开发环境硬件基本组成

    2.开发板启动流程

    3.搭建嵌入式Linux开发环境的主要工作

    4.开发主机搭建

    5.TFTP 服务

    6.NFS 服务

    7.目标机安装(u-boot烧写调试) –  需要SD卡

    8.fastboot烧写

    02Bootloader移植(bootloader基本概念,U-boot常用命令和配置编译

    1.Bootloader 介绍

    1.什么是Bootloader

    2.Bootloader的特点

    3.Bootloader的操作模式

    2.常用bootloader介绍

    3.U-boot介绍

    4.U-boot命令介绍

    1.printenv 显示所有环境变量

    2.setenv 设置新的环境变量

    3.saveenv 将当前定义的所有的环境变量值存入flash中

    4.tftp 通过网络下载程序

    5.protect 对Nor Flash写保护

    6.erase 擦除Nor FLASH

    7.Nand相关命令

    8.movi 命令

    9.bootcmd 自启动命令

    10.bootm kernel-addr ramdisk-addr dtb-addr

    11.go addr

    5.U-BOOT 配置编译

    1.U-Boot目录结构

    2.编译U-boot

    3.U-boot镜像下载烧录

    03U-boot启动流程, U-boot移植

    1.U-BOOT 启动流程

    1.1u-boot启动三个2

    1.2启动步骤(重点)

    2.U-boot 启动源码分析

    2.1第一条指令位置

    2.2u-boot的启动入口

    2.3基本硬件初始化

    2.4大部分硬件初始化

    2.5BootLoader两种模式切换

    3.u-boot 启动分析

    3.1u-boot环境变量设置

    3.2u-boot启动阶段

    3.3linux内核启动阶段

    3.4根文件系统阶段(可运行应用程序)

    4.U-BOOT 移植方法

    04Linux内核分析(Linux内核基本概念,Linux内核启动分析,Linux内核调试方法)

    1.Linux内核基本概念

    1.1Linux内核

    1.2主流的 Linux 发行版

    1.3Linux 内核的特性

    1.4Linux内核版本

    Linux内核子系统

    1.5Linux内核模块结构图

    2.linux内核编译(移植好的)

    2.1编译内核 make uImage

    2.2编译设备树 make dtbs

    2.3Linux内核代码结构(1)

    2.4Linux系统源代码目录结构(2)

    Linux内核启动分析

    3.嵌入式系统启动信息分析

    3.1u-boot启动阶段

    3.2linux内核启动阶段

    3.3根文件系统阶段(可运行应用程序)

    3.4嵌入式系统 启动流程

    3.5内核启动流程

    4.Linux内核调试方法

    4.1内核调试方法1:点灯法

    4.2内核调试方法 2:printk打印输出信息

    4.3内核调试方法 3: OOP内核异常信息

    05Linux内核移植及网卡移植

    1.Linux内核 配置编译

    1.1下载内核源码

    1.2Linux系统中解压

    1.3修改Makefile指定交叉编译工具链

    1.4配置内核 make menuconfig

    1.5编译内核 make uImage

    1.6编译设备树 make dtbs

    1.7网卡移植

    出错分析

    2.网卡移植—平台无关

    2.1配置内核支持网络

    2.2置设备树描述网卡和CPU的链接情况

    2.3修改文件driver/clk/clk.c

    3.CPU与设备连接描述 - 设备树DeviceTree

    3.1网卡对应的CPU内部总线节点的描述

    3.2网卡节点的描述

    4.CPU与设备连接描述 - 平台设备

    06第三方驱动移植(驱动编译进内核Makefile,图像化配置Kconfig,驱动模块,黑白盒对比)

    1.第三方驱动 黑盒移植

    2.驱动编译进内核Makefile

    2.1选择驱动存放目录 (或任意目录)

    2.2改Makefile让驱动编译进内核(同步修改,对应目录下的Makefile)

    2.3改Kconfig (界面可配置)

    2.4编译并拷贝至根文件系统​2.5在开发板上运行该测试程序​分析这个打印信息的来源​3.需要创建设备文件

    3.1创建设备文件

    4.图形化配置Kconfig

    make menuconfig、Makefile、Kconfig、.config 三者的关系

    4.1配置Kconfig

    5.编译驱动为独立的模块

    5.1C程序代码编写

    5.2Makefile 编写

    5.3编译出 ko 模块

    配置为模块方式

    5.4make modules 编译所有的模块

    5.5在linux运行时,可以装载和卸载模块

    6.白盒移植

    黑白盒对比

    驱动框架

    字符设备框架

    字符设备引入

    字符设备驱动相关

    平台设备框架

    07植根文件系统制作(根文件系统基本概念,根文件系统设备,访问根文件系统制作)

    1.根文件系统基本概念

    1.1什么是根文件系统?

    1.2根文件系统主要目录结构

    1.3程序文件的放置

    1.4定制应用程序

    1.5库文件的放置

    2.Linux 设备文件

    举例

    2.1字符设备举例

    2.2块设备举例

    2.3设备的主设备号次设备号

    3.创建设备节点

    4.Linux系统的引导过程

    制作根文件系统   

    5.文件系统制作步骤

    6.BusyBox项目构建系统命令

    7.BusyBox工具安装

    8.测试

    文件 /etc/inittab

    文件 /etc/fstab

    文件 /etc/profile

    制作需要的rootfs类型的格式

    不同根文件系统详解

    nfs rootfs

    CRAMFS

    JFFS2和YAFFS2

    EXT2 over RAM disk

    制做EXT2 over RAM disk文件系统


    01嵌入式基本概念,嵌入式开发环境搭建,目标机搭建,TFTP服务搭建,NFS服务搭建

    1.系统移植概述及环境搭建

    1.通用嵌入式系统软件组成部分

    • 无os嵌入式系统组成图
      在这里插入图片描述
    • 有os嵌入式系统组成图
      在这里插入图片描述

    2.Linux 在嵌入式中应用的条件与前景

    嵌入式系统越来越追求数字化、网络化和智能化。这就要要求整个嵌入式系统必须是开放的、提供标准的API,并且能够方便地与众多第三方的软硬件沟通。
    Linux是在GPL协议下开放源码的系统,内核可以定制剪裁、功能强大、支持多种文件系统、网络功能及其强大、非常适合高端嵌入式系统。
    更重要的是 linux 不仅仅支持X86体系结构的cpu,还支持众多的体系结构的 cpu/mcu。
    Android 系统最初就是基于linux-2.6.23的。硬件基本要求 armv5 ARM926EJ-S 200Mhz 64M

    3.嵌入式Linux内核结构

     

    4.Android系统

    2.嵌入式开发环境搭建

    1.嵌入式Linux交叉开发环境硬件基本组成

    1. 开发主机(Host)
    2. 目标机(Target)
    3. 连接介质

    2.开发板启动流程

    在这里插入图片描述

    3.搭建嵌入式Linux开发环境的主要工作

    1. 准备开发主机、目标机(开发板)以及二者的连接介质
    2. 准备目标机代码
    3. 安装交叉工具链
    4. 开发主机上安装的软件(为方便调试)
    5. 终端软件(putty、minicom)
    6. tftp服务
    7. nfs服务
    8. 目标机安装(u-boot烧写调试)SD卡方式  Fastboot方式 (成功后,板子有串口信息输出)
    9. 主机和目标机能联通
    10. 网络自动 tftp 加载内核,并挂载nfs rootfs 启动

    4.开发主机搭建

     

    ubuntu环境

     

    5.TFTP 服务

     

    主机端tftp服务器配置

    6.NFS 服务

    7.目标机安装(u-boot烧写调试) –  需要SD卡

    制作SD卡,并从SD卡启动 (使用的是2010版本u-boot,支持fastboot烧写的)

    将sdfuse_q 拷贝到Linux下
    将SD卡插入电脑并识别
    进入sdfuse_q执行如下操作

     $ sudo ./mkuboot.sh /dev/sdb 
    

    出现下面的信息,表示SD启动盘制作成功

    Fuse FS4412 trustzone uboot file into SD card
    /dev/sdb reader is identified.
    u-boot-fs4412.bin fusing...
    1029+1 records in
    1029+1 records out
    527104 bytes (527 kB) copied, 5.31834 s, 99.1 kB/s
    u-boot-fs4412.bin image has been fused successfully.
    Eject SD card
    

    关闭开发板电源,将拨码开关SW1调至(1000)(SD启动模式)
    刚才做好的SD启动盘插入SD卡插槽
    打开电源

    8.fastboot烧写

    	连接USB线到板子上的USB OTG口 
    	连接串口线到板子的COM2口   
    	重启板子,并快速停下,在串口终端输入下面命令 /*
    						  如果有有需要,可以格式化 eMMC 并创建分区
    						  $ fdisk -c 0
    					    $ fatformat mmc 0:1
    					    $ ext3format mmc 0:2
    					    $ ext3format mmc 0:3
    					    $ ext3format mmc 0:4
        */
      $ reset    重启切换到2010版的sd卡启动  
      $ fastboot  //会提示装驱动,选中第一天_环境搭建里的fastboot_driver 安装 	
      打开dos终端 进入USB_fastboot_tool\platform-tools目录输入
      > fastboot.exe flash bootloader u-boot-fs4412.bin  /*
              同理可以烧录其它镜像
    			    > fastboot.exe flash kernel zImage
    				  > fastboot.exe flash ramdisk ramdisk-uboot.img
    			    > fastboot.exe flash system system.img
    			    > fastboot -w
           */
      
      关闭开发板电源,将拨码开关SW1调至0110(EMMC启动模式)后打开电源
      从flash 的u-boot启动  /*
          如果启动失败,可以通过拨号开关恢复到SD卡方式启动
          如果启动成功,想恢复到原来的u-boot启动 (第一次输入reset后会自动切换回去,不用拔拨号开关)   
        */
    

     

    IP地址设置

    板子能ping通虚拟机 (要关闭防火墙 网卡右键高级)
    |板子 192.168.2.10 |
    --------------------------
    ------------------------
    |电脑 192.168.2.112 | //做中转用,和板子虚拟机IP要在同一网段, 且不能和它们IP一样
    ------------------------
    ------------------------
    |虚拟机 192.168.2.231 |

    确认板子和电脑是能通信的

    设置电脑网卡ip 为192.168.2.112 255.255.255.0 192.168.9.1
    启动板子,快速按任意键停在boot处,设置u-boot 的环境变量

    #setenv serverip 192.168.2.231    //注意它与虚拟机里 ubuntu 的ip要一致
    #setenv ipaddr 192.168.2.10
    #setenv gatewayip  192.168.2.1
    

    #pri 查看设置后效果

    FS4412 # pri
    baudrate=115200
    bootargs=root=/dev/nfs nfsroot=192.168.9.120:/nfs/rootfs rw console=ttySAC2,115200 clk_ignore_unused init=/linuxrc ip=192.168.9.9
    bootcmd=tftp 41000000 uImage;tftp 42000000 exynos4412-fs4412.dtb;bootm 41000000 - 42000000
    bootdelay=3
    ethact=dm9000
    ethaddr=11:22:33:44:55:66
    gatewayip=192.168.2.1
    ipaddr =192.168.2.10
    netmask=255.255.255.0
    serverip=192.168.2.231
    

    #ping 192.168.2.231
    测试网络是否连通 ,注意在u-boot中, 它能ping电脑, 电脑不能ping它 ,注意,要拔掉jtag线,否则ping 会重启
    host 192.168.2.231 is alive //is alive 表示ok

    确认电脑和虚拟机时能通信

    编辑 -> 虚拟网络编辑器 -> VMnet0 桥接到(选连板子的网卡) //注意不要用automic,应手动指定对应的网卡
    虚拟机 -> 设置 -> 网卡适配器 -> 自定义 (选 VMnet0)
    使虚拟机内的虚拟网卡,关联到电脑实际用到的网卡
    通过选VMnet0 和 VMnet1 。实现连板子,还是上internet的切换

    网络自动 tftp 加载内核,并挂载nfs rootfs 启动

    1. 设置tftp方式加载内核
      setenv bootcmd tftp 41000000 uImage;tftp 42000000 exynos4412-origen.dtb;bootm 41000000 - 42000000
      setenv bootcmd 设置环境变量(自启动命令 bootcmd)
      tftp 41000000 uImage; 通过tftp从虚拟机/tftpboot目录下下载内核uImage到板子的内存 41000000 处。 ; 用于分割多个命令
      tftp 42000000 exynos4412-origen.dtb 通过tftp下载设备树文件 exynos4412-fs4412.dtb 到板子的内存 42000000 处
      bootm 41000000 - 42000000 启动内核(41000000处放的是内核uImage, 42000000处放的是设备树文件)

    2. 挂载nfs rootfs
      setenv bootargs root=/dev/nfs nfsroot=192.168.2.231:/nfs/rootfs rw console=ttySAC2,115200 clk_ignore_unused init=/linuxrc ip=192.168.2.10

      setenv bootarg 设置环境变量( bootarg是启动参数)
      root=/dev/nfs 指定根文件系统类型是 nfs
      nfsroot=192.168.2.231:/source/rootfs 指定source rootfs的位置 (是在ip 是192.168.2.231的机器上 ,的/source/rootfs目录下). 注意/nfs/rootfs必须和前面NFS服务配置文件设置一致

    3. savenenv //保存环境变量
      掉电重启动板子 看能否挂载nfs rootfs成功
      能看到下面信息表示成功
      [root@farsight ]# ls
      etc linuxrc proc sbin tmp var
      bin dev lib mnt root sys usr
      在里面创建文件,电脑的/nfs/rootfs上同步变化

    02Bootloader移植(bootloader基本概念,U-boot常用命令和配置编译

    1.Bootloader 介绍

    1.什么是Bootloader

    • Bootloader是硬件启动的引导程序,是运行操作系统的前提;
    • 在操作系统内核或用户应用程序运行之前运行的一小段代码。对软硬件进行相应的初始化和设定,为最终运行操作系统准备好环境;
    • 在嵌入式系统中,整个系统的启动加载任务通常由Bootloader来完成。

    2.Bootloader的特点

    • Bootloader不属于操作系统,一般采用汇编语言和C语言开发。需要针对特定的硬件平台编写。
    • 在移植系统时,首先为开发板移植Bootloader。
    • Bootloader不但依赖于CPU的体系结构,而且依赖于嵌入式系统板级设备的配置。

    3.Bootloader的操作模式

    • 自启动模式:在这种模式下,Bootloader从目标机上的某个固态存储设备上将操作系统加载到RAM中运行,整个过程并没有用户的介入。
    • 交互模式:在这种模式下,目标机上的Bootloader将通过串口或网络等通信手段从开发主机(Host)上下载内核映像和根文件系统映像等到RAM中。可以被 Bootloader写到目标机上的固态存储媒质中,或者直接进行系统的引导。也可以通过串口接收用户的命令。

    2.常用bootloader介绍

    在这里插入图片描述

    3.U-boot介绍

    u-boot(Universal Boot Loader)是德国DENX小组开发的用于多种嵌入式CPU的bootloader程序。遵循GPL条款。
    从FADSROM、8xxROM 、PPCBOOT、Armboot逐步发展演化而来;
    当前版本号:参考Makefile。
    http://www.denx.de/wiki/U-Boot/WebHome
    U-boot的特点:
    代码结构清晰、易于移植(见目录结构)
    支持多种处理器体系结构(见arch目录)
    支持众多开发板(目前官方包中有200多种,见board目录)
    命令丰富、有监控功能
    支持网络协议、USB、SD等多种协议和设备
    支持文件系统
    更新较活跃,使用者多,有助于解决问题

    4.U-boot命令介绍

    命令分类
    环境设置、数据传输、存储器访问、加载运行

    1.printenv 显示所有环境变量

    ORIGEN # pri
    

    在这里插入图片描述

    2.setenv 设置新的环境变量

    ORIGEN # set myboard FS4412 
    ORIGEN # pri
    

    在这里插入图片描述

    3.saveenv 将当前定义的所有的环境变量值存入flash中

    在这里插入图片描述

    4.tftp 通过网络下载程序

    U-boot # setenv ethaddr 11:22:33:44:55:66 //设置开发板的物理地址

       U-boot # setenv  ipaddr  192.168.2.10
       U-boot # setenv  serverip  192.168.2.231
       U-boot # tftp  41000000  application.bin
       U-boot # tftp  41000000  zImage
    

    5.protect 对Nor Flash写保护

    protect on 0 10000 对区间[0x0, 0x10000]进行写保护
    protect off 0 10000 对上述区间取消写保护
    

    6.erase 擦除Nor FLASH

    erase all 擦除FLASH所有的扇区
    erase 0 10000 把FLASH区间 [0x0, 0x10000]擦除
    

    7.Nand相关命令

    nand read addr off size
    nand write addr off size
    nand erase [clean] [off size]
    

    NAND flash和NOR flash的区别详解 https://zhidao.baidu.com/question/1993729068599410707.html
    NAND flash按块访问和NOR flash按字节访问
    NAND flash必须先擦出后写

    8.movi 命令

    eMMC

    movi init —初始化eMMC并显示相关信息
    movi read u-boot/kernel addr //读u-boot或读kernel,可以选择
    movi write u-boot/kernel addr
    movi read rootfs addr size
    movi write rootfs addr size
    

    9.bootcmd 自启动命令

    如果定义了该变量,在自启动模式下将会执行该环境变量中的命令。
    将文件通过tftp自动下载到指定的地址
    U-boot # setenv bootcmd tftp 41000000 uImage; bootm 41000000
    U-boot # saveenv
    在这里插入图片描述

    bootargs 是uboot传递给内核到启动参数,是一个字符串
    console=xxx: 告诉内核启动时候到调试信息是从哪个设备输出,这里是串口2
    init=xxx:  告诉内核linux到第一个用户进程是什么
    root=xxx : 告诉内核根文件系统在哪里
    root=/dev/nfs 表示根文件系统在网路远端
    nfsroot=(开发板)ip:path rw     其中rw表示可读可写
    ip=xxx :(Ubuntu ip)告诉内核开机的时候内核的ip地址是多少(静态分配ip)
    

     

    在这里插入图片描述

    10.bootm kernel-addr ramdisk-addr dtb-addr

    引导内核为内核传参,其中内核和ramdisk通常为mkimage处理过的二进制文件。
    从这个地址处自动启动程序
    在这里插入图片描述

    11.go addr

    执行内存中的二进制代码,简单的跳转到指定地址(运行裸机程序)

    5.U-BOOT 配置编译

    1.U-Boot目录结构

    • 平台相关
      arch, board, include…
    • 平台无关
      common, net, fs, drivers…
    • 工具和文档
      tools, doc
      在这里插入图片描述

    2.编译U-boot

    • U-boot的编译
      整个工程通过Makefile来组织编译。顶层目录下的Makefile中包含了开发板的配置信息。从顶层目录开始递归地调用各级子目录下的Makefile,最后链接成u-boot映像。
    • 顶层目录下的 Makefile
      它负责u-boot整体配置和编译
      在Makefile中指定使用的交叉工具链
      配置u-boot: make origen_config
      编译: make

    使用build.sh编译

    linux@linux:~/u-boot-2013.01-fs4412$ ./build.sh

    查看build.sh

    #!/bin/sh
    
    sec_path="CodeSign4SecureBoot/"
    CPU_JOB_NUM=$(grep processor /proc/cpuinfo | awk '{field=$NF};END{print field+1}')
    ROOT_DIR=$(pwd)
    CUR_DIR=${ROOT_DIR##*/}
    
    case "$1" in
    	clean)
    		echo make clean
    		make mrproper
    		;;
    	*)
    			
    		if [ ! -d $sec_path ]
    		then
    			echo "**********************************************"
    			echo "[ERR]please get the CodeSign4SecureBoot first"
    			echo "**********************************************"
    			return
    		fi
    		
    		make fs4412_config
    		
    		make -j$CPU_JOB_NUM
    		
    		if [ ! -f checksum_bl2_14k.bin ]
    		then
    			echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
    			echo "There are some error(s) while building uboot, please use command make to check."
    			echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
    			exit 0
    		fi
    		
    		cp -rf checksum_bl2_14k.bin $sec_path
    		cp -rf u-boot.bin $sec_path
    		rm checksum_bl2_14k.bin
    		
    		cd $sec_path
    		cat E4412_N.bl1.SCP2G.bin bl2.bin all00_padding.bin u-boot.bin tzsw_SMDK4412_SCP_2GB.bin > u-boot-fs4412.bin
    		mv u-boot-fs4412.bin $ROOT_DIR
    		
    		rm checksum_bl2_14k.bin
    		rm u-boot.bin
    
    		echo 
    		echo 
    		;;
    		
    esac
    

    U-BOOT编译生成的映像文件

    在这里插入图片描述

    3.U-boot镜像下载烧录

    烧录编译产生的镜像 u-boot.bin
    初次或开发板代码损坏不能正常启动时,可采用JTAG工具烧录
    专用的烧录工具如h-jtag或DNW等
    在u-boot已经能工作,升级或修正U-boot时,可用U-boot中的命令来烧录
    其它方式 如SD卡 , Fastboot命令
    镜像固化位置
    ROM、NOR FLASH、NAND FLASH EMMC等

    u-boot-fs4412.bin

    1. u-boot.bin是uboot编译源码后直接产生的,一般的的开发板,直接烧写这个文件就可以了
    2. 但是三星的cortex_a9 exynos4412这款CPU把uboot中一些初始化时钟等的代码剥离出去了,所以,编译好的这个u-boot.bin还要加上被剥离出去的部分,才可以正常使用
    3. 所以在build.sh脚本文件中,在u-boot.bin之前加上了剥离出去的部分后,生成了u-boot-fs4412.bin
      在这里插入图片描述

     

    03U-boot启动流程, U-boot移植

    1.U-BOOT 启动流程

    1.1u-boot启动三个2

    1. 两个阶段:汇编阶段(特殊功能寄存器C语言不能直接访问,C运行之前需要准备堆栈),C阶段

    2. 两次搬移:u-boot自搬移,内核搬移

    3. 两次初始化:基本硬件初始化,大部分硬件初始化

       第一条指令位置(参考u-boot.map)  arch/arm/cpu/armv7/start.S  里的 _start: b	reset 
       设置为SVC模式          msr	cpsr,r0
       关闭MMU Cache          cpu_init_cp15    
       基本硬件设备初始化     board/samsung/fs4412/lowlevel_init.S 的  lowlevel_init   
                               关中断 看门狗(时钟  串口,flash,内存等的初始化时间可能比较长,这样的话,看门狗会使开发板不停的重启,所以在初始化硬件之前,先关闭MMU Cache,关中断 看门狗) 
                               ,初始化时钟  串口,flash,内存
       自搬移到内存           relocate_code  
       						(把u-boot剩下的部分搬到内存中,然后运行)
       设置栈,               IRQ stack frame 
       						(C代码运行之前,必须先设置栈)
       
       准备进入C部分          bl	_main ( 参u-boot.map )  
       大部分硬件初始化       arch\arm\lib\board.c\board_init_f  里的init_sequence 
       搬移内核到内存运行     common/main.c  main_loop -> getenv ("bootcmd")  
                                  bootdelay >=     0 && s    && !abortboot (bootdelay)) 
                                   下的 run_command (bootcmd)
      

    发板上的EMMC里面,开发板上电后,BootLoader运行,

    设置为SVC模式,关闭MMUCache,基本硬件初始化,

    自搬移到内存(uboot剩余程序进内存),设置栈,准备进入C语言部分,

    大部分硬件初始化,搬移内核到内存(通过网络—tftp服务,将uImage和设备树文件加载到内存)

    挂载根文件系统(通过网络—nfs服务,将rootfs加载到内存)

    1.2启动步骤(重点)

    1. 上电启动bootloader
      硬件基本初始化
      自搬移到内存
      搬移内核到内存
      传递内核启动参数(parmer_struct 或taglist)
    2. 加载内核
      a. 自解压内核 decompess //arch/arm/boot/compressed/head.S
      b. 运行内核汇编部分 head.S 入口stext //arch/arm/kernel/head.S
      检测合法性(CPU 类型,机器类型)
      c. 运行内核C部分 start_kernel //init/main.c
      CPU,机器参数的安装 setup_arch
      中断,定时,终端,内存等最基本的初始化
      创建核心进程 kernel_init运行,启动多任务调度,原父进程空转cpu_ide
    3. 挂载rootfs (mount_root)
    4. 运行应用程序 //第一个应用程序是init (由u-boot的bootargs里的init=/linuxrc来指定)
      a. 运行启动脚本 (run_init_process("/etc/init.d/rcS")) //由init来解析脚本执行
      b. 其它应用程序 //一般添加在脚本的最后(如在rcS末尾加 ./app)

    2.U-boot 启动源码分析

    • 上电系统从哪里开始,启动代码放在什么位置 ?
      上电后,有的系统可通过硬件管脚的电平来选择从Nandflash还是从Norflash启动。这里是指定从Nandflash启动的
      启动代码U-boot 是不能放在RAM中的,因掉电就消失了。

    • boot第一件是为何是设置为SVC模式?
      为安全性,CPU本身提出了多种模式来实现安全性,和效率兼顾。
      SVC模式就是CPU对资源的一种保护。在普通用户模式是不能访问到的。只有切换到SVC模式才能访问。

    • 为什么并关闭中断,MMU,看门狗等?
      初始时为安全性,把系统单纯化, 排除掉别的干扰,仅仍u-boot实现单纯的搬移代码,
      的功能。 所以关掉中断,避免中断打断带来的保存返回的问题。 关掉MMU,因为u-boot软件是硬件实地址访问。
      根本没有用到内存地址映射。 看门狗如果没关,硬件上默认到时会复位的。 所以要关掉

    • 为何设备初始引导不能用C代码,要用汇编代码?
      特殊指令,如操作协处理器, MMC CASH ,切换SVC模式, 等C不能做到。

    • U-BOOT为何要搬移到RAM中运行?
      在RAM中速度更快,但因掉电就没了,所以要保存在Nandflash或Norflash中。
      如果搬移,直接在Norflash上运行也是可以的。 Nandflash因是按块操作的,不太合适直接运行。

    • U-boot如何传递参数到内核。 移植时要注意哪些?
      方式一 采用param_struct: (我们现在使用的是这种方式) 见common/cmd_boot.c go命令的优化
      方式二 采用taglist:

    /—u-boot 的启动步骤(重点)
    //阶段一(汇编)
    设置为SVC模式,关闭中断,MMU,看门狗 //准备
    基本硬件设备初始化 //初始化时钟,串口,flash,内存 见cpu/arm_cortexa8/start.S 的 cpu_init_crit
    自搬移到内存 //copy_uboot_to_ram 或relocate
    设置好栈 //stack_setup
    跳转到第二阶段代码入口 //ldr pc, _start_armboot
    //阶段二(C语言)
    大部分硬件初始化 //lib_arm/board.c/start_armboot -> init_sequence
    搬移内核到内存 //common/main.c main_loop -> getenv (“bootcmd”) bootdelay >= 0 && s && !abortboot (bootdelay)) 下的 run_command (bootcmd)
    运行内核

    2.1第一条指令位置

    {//---u-boot.lds  或 u-boot.map    指明了第一条指令位置
    	arch/arm/cpu/armv7/start.o     
    }   
    

    2.2u-boot的启动入口

    {//---arch/arm/cpu/armv7/start.S    u-boot的启动入口
    _start: b	reset   
    	ldr	pc, _undefined_instruction
    	ldr	pc, _software_interrupt
    	ldr	pc, _prefetch_abort
    	ldr	pc, _data_abort
    	ldr	pc, _not_used
    	ldr	pc, _irq
    	ldr	pc, _fiq	
    	
    reset:
    	/*
    	 * set the cpu to SVC32 mode
    	 */
    	mrs	r0, cpsr
    	bic	r0, r0, #0x1f
    	orr	r0, r0, #0xd3
    	msr	cpsr,r0	
    	
    	bl	cpu_init_cp15   //关闭中断 cache MMU等
    	bl	cpu_init_crit
    
    	bl	_main	         //跳到C部分  位置  arch/arm/lib/board.c   ( 在u-boot.map里搜索_main) 
    		
    
    ENTRY(relocate_code)   //自搬移 重定位   (运行时机见  u-boot.map 里执行位置)
    	adr	r0, _start
    	cmp	r0, r6
    	moveq	r9, #0		/* no relocation. relocation offset(r9) = 0 */
    	beq	relocate_done		/* skip relocation */
    	mov	r1, r6			/* r1 <- scratch for copy_loop */
    	ldr	r3, _image_copy_end_ofs
    	add	r2, r0, r3		/* r2 <- source end address	    */
    copy_loop:
    	ldmia	r0!, {r9-r10}		/* copy from source address [r0]    */
    	stmia	r1!, {r9-r10}		/* copy to   target address [r1]    */
    	cmp	r0, r2			/* until source end address [r2]    */
    	blo	copy_loop		
    ENDPROC(relocate_code)		
    		
    		
    ENTRY(cpu_init_cp15)
    	/*
    	 * Invalidate L1 I/D
    	 */
    	mov	r0, #0			@ set up for MCR
    	mcr	p15, 0, r0, c8, c7, 0	@ invalidate TLBs
    	mcr	p15, 0, r0, c7, c5, 0	@ invalidate icache
    
    	/*
    	 * disable MMU stuff and caches
    	 */
    	mrc	p15, 0, r0, c1, c0, 0
    	bic	r0, r0, #0x00002000	@ clear bits 13 (--V-)
    	bic	r0, r0, #0x00000007	@ clear bits 2:0 (-CAM)
    	mcr	p15, 0, r0, c1, c0, 0
    	mov	pc, lr			@ back to my caller
    ENDPROC(cpu_init_cp15)	
    
    	
    ENTRY(cpu_init_crit)
    	b	lowlevel_init		@ go setup pll,mux,memory   //位置board/samsung/fs4412/libfs4412.o( 在u-boot.map里搜索lowlevel_init) 
    ENDPROC(cpu_init_crit)	
    	
    	
    }	  
    

    2.3基本硬件初始化

    {//---board/samsung/fs4412/lowlevel_init.S   基本硬件初始化   (关闭看门狗中断  时钟初始化 串口初始化 nand初始化 dram初始化)
    lowlevel_init:      //有些初始化,已被三星剥离到 BLO或BL1	中  
    	/* init system clock */
    	bl system_clock_init
    
    	/* Memory initialize */
    	bl mem_ctrl_asm_init
    
    	/* for UART */
    	bl uart_asm_init	
    	mov	pc, lr	
    }	 
    

    2.4大部分硬件初始化

    {//---arch/arm/lib/board.c   大部分硬件初始化,  调用主循环main_loop(见common/main.c)
    	init_fnc_t *init_sequence[] = {
    		arch_cpu_init,		/* basic arch cpu dependent setup */
    		mark_bootstage,
    	#if defined(CONFIG_BOARD_EARLY_INIT_F)
    		board_early_init_f,
    	#endif
    		timer_init,		/* initialize timer */
    		env_init,		/* initialize environment */
    		init_baudrate,		/* initialze baudrate settings */
    		serial_init,		/* serial communications setup */
    		console_init_f,		/* stage 1 init of console */
    		display_banner,		/* say that we are here */
    		dram_init,		/* configure available RAM banks */
    		NULL,
    	};	
    		
    	
    	void board_init_r(gd_t *id, ulong dest_addr)
    	{
    		board_init();	/* Setup chipselects */
    		
    		/* main_loop() can return to retry autoboot, if so just run it again. */
    		for (;;) {
    			main_loop(); //调用主循环main_loop
    		}
    	}	
    	
    	void board_init(ulong bootflag)
    	{
    		for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {  //大部分硬件初始化
    			if ((*init_fnc_ptr)() != 0) {
    				hang ();
    			}
    		}
    	}
    	
    	
    	
    }
    

    2.5BootLoader两种模式切换

    {//5.common/main.c   //主循环main_loop 实现 bootdelay延时时间到之前无输入,则加载bootcmd进入自启动模式;如果有输入则进入交互模式
      void main_loop (void)
    	{
    	
    		s = getenv ("bootdelay");
    		bootdelay = s ? (int)simple_strtol(s, NULL, 10) : CONFIG_BOOTDELAY;
    	
    	  s = getenv ("bootcmd");  //获取自启动命令如 bootcmd = tftp 20008000 zImage ; go zImage 表示从网络加载内核运行
    	
    	
    	  if (bootdelay >= 0 && s && !abortboot (bootdelay)) {
            run_command (s, 0);            //如果延时大于等于零,并且没有在延时过程中接收到按键,则运行bootcmd命令,引导内核。进入自启动模式
        }
    	
    	 //否则进入交互模式 
    		/*
    		 * Main Loop for Monitor Command Processing
    		 */
    		for (;;) {
    				len = readline (CONFIG_SYS_PROMPT);      //读取命令
    		
    				rc = run_command (lastcommand, flag);    //运行命令
    
    		}
      }	
    }  
       
    }	
    			
    }
    

    3.u-boot 启动分析

    3.1u-boot环境变量设置

    ORIGEN # pri
    baudrate=115200
    bootargs=root=/dev/nfs nfsroot=192.168.2.231:/nfs/rootfs rw console=ttySAC2,115200 clk_ignore_unused init=/linuxrc ip=192.168.2.10
    bootcmd=tftp 41000000 uImage;tftp 42000000 exynos4412-origen.dtb;bootm 41000000 - 42000000
    bootdelay=3
    ethact=dm9000
    ethaddr=11:22:33:44:55:66
    fileaddr=42000000
    filesize=8400
    gatewayip=192.168.2.1
    ipaddr=192.168.2.10
    myboard=FS4412
    netmask=255.255.255.0
    serverip=192.168.2.231
    stderr=serial
    stdin=serial
    stdout=serial
    

    Environment size: 498/16380 bytes

    3.2u-boot启动阶段

    {//-------u-boot启动阶段
    	U-Boot 2013.01 (Aug 24 2014 - 12:01:19) for FS4412
    	CPU:	Exynos4412@1000MHz
    	Board: FS4412
    	DRAM:  1 GiB
    	WARNING: Caches not enabled
    	MMC:   MMC0:	3728 MB
    	In:    serial
    	Out:   serial
    	Err:   serial
    	MMC read: dev # 0, block # 48, count 16 ...16 blocks read: OK
    	eMMC CLOSE Success.!!
    	Checking Boot Mode ... EMMC4.41
    	Net:   dm9000
    	Hit any key to stop autoboot:  3  2  1  0 
    
    	dm9000 i/o: 0x5000000, id: 0x90000a46 
    	DM9000: running in 16 bit mode
    	MAC: 11:22:33:44:55:66
    	operating at 100M full duplex mode
    	Using dm9000 device
    	TFTP from server 192.168.9.120; our IP address is 192.168.9.9  //对应bootcmd的 tftp 0x41000000 uImage 
    	Filename 'uImage'.
    	Load address: 0x41000000
    	Loading: *#################################################################
    		 #################################################################
    		 #################################################################
    		 #################################################################
    		 #################################################################
    		 #################################################################
    		 #################################################################
    		 #################################################################
    		 #################################################################
    		 #######
    		 69.3 KiB/s
    	done
    	Bytes transferred = 3028040 (2e3448 hex)
    	dm9000 i/o: 0x5000000, id: 0x90000a46 
    	DM9000: running in 16 bit mode
    	MAC: 11:22:33:44:55:66
    	operating at 100M full duplex mode
    	Using dm9000 device
    	TFTP from server 192.168.9.120; our IP address is 192.168.9.9  //对应bootcmd的 tftp 42000000 exynos4412-fs4412.dtb 
    	Filename 'exynos4412-fs4412.dtb'.
    	Load address: 0x42000000
    	Loading: *#######
    		 393.6 KiB/s
    	done
    	Bytes transferred = 33876 (8454 hex)
    	   Booting kernel from Legacy Image at 41000000 ...
    	   Image Name:   Linux-3.14.0
    	   Image Type:   ARM Linux Kernel Image (uncompressed)
    	   Data Size:    3027976 Bytes = 2.9 MiB
    	   Load Address: 40008000
    	   Entry Point:  40008000
    	   Verifying Checksum ... OK
    	   Flattened Device Tree blob at 42000000
    	   Booting using the fdt blob at 0x42000000
    	   Loading Kernel Image ... OK
    	   Loading Device Tree to 4fff4000, end 4ffff453 ... OK
    	   
    	Starting kernel ...   /*启动内核(对应bootmcd的 bootm 41000000 - 42000000)
    								如果到这里启动失败,可能原因      
    						    1.u-boot参数设置错误   如bootargs 中ttySAC2 设为了ttySAC1  
    						    2.uImage 有问题。   换一个OK的试试,或把这个uImage放在别的板上验证下
    						    3.内核源码有问题, 加打印信息跟踪和打开内核调试信息开关,   init\main.c  start_kernel()
    						        如machine type 不匹配
    						    4.硬件相关,如u-boot初始CPU频率,分频不对 
    						    */    
    

    3.3linux内核启动阶段

    Booting Linux on physical CPU 0xa00
    //init\main.c  start_kernel()
    Linux version 3.14.0 (david@ubuntu) (gcc version 4.6.4 (crosstool-NG hg+default-2685dfa9de14 - tc0002) ) #23 SMP PREEMPT Fri Aug 15 11:30:16 CST 2014
    
    CPU: ARMv7 Processor [413fc090] revision 0 (ARMv7), cr=10c5387d
    
    CPU: PIPT / VIPT nonaliasing data cache, VIPT aliasing instruction cache
    
    Machine model: Insignal Origen evaluation board based on Exynos4412
    
    Memory policy: Data cache writealloc
    
    CPU EXYNOS4412 (id 0xe4412011)
    
    Running under secure firmware.
    
    PERCPU: Embedded 7 pages/cpu @eefb6000 s7424 r8192 d13056 u32768
    
    Built 1 zonelists in Zone order, mobility grouping on.  Total pages: 256528
    
    Kernel command line: root=/dev/nfs nfsroot=192.168.9.120:/nfs/rootfs rw console=ttySAC2,115200 init=/linuxrc ip=192.168.9.9  //内核对u-boot传入的bootargs参数的解析
    
    PID hash table entries: 4096 (order: 2, 16384 bytes)
    
    Dentry cache hash table entries: 131072 (order: 7, 524288 bytes)
    
    Inode-cache hash table entries: 65536 (order: 6, 262144 bytes)
    
    Memory: 1016852K/1032192K available (3956K kernel code, 237K rwdata, 1320K rodata, 231K init, 276K bss, 15340K reserved, 270336K highmem)
    
    Virtual kernel memory layout:
    
        vector  : 0xffff0000 - 0xffff1000   (   4 kB)
    
        fixmap  : 0xfff00000 - 0xfffe0000   ( 896 kB)
    
        vmalloc : 0xf0000000 - 0xff000000   ( 240 MB)
    
        lowmem  : 0xc0000000 - 0xef800000   ( 760 MB)
    
        pkmap   : 0xbfe00000 - 0xc0000000   (   2 MB)
    
        modules : 0xbf000000 - 0xbfe00000   (  14 MB)
    
          .text : 0xc0008000 - 0xc052f41c   (5278 kB)
    
          .init : 0xc0530000 - 0xc0569d00   ( 232 kB)
    
          .data : 0xc056a000 - 0xc05a5540   ( 238 kB)
    
           .bss : 0xc05a554c - 0xc05ea584   ( 277 kB)
    
    SLUB: HWalign=64, Order=0-3, MinObjects=0, CPUs=4, Nodes=1
    
    Preemptible hierarchical RCU implementation.
    
    	RCU restricting CPUs from NR_CPUS=8 to nr_cpu_ids=4.
    
    RCU: Adjusting geometry for rcu_fanout_leaf=16, nr_cpu_ids=4
    
    NR_IRQS:16 nr_irqs:16 16
    
    Exynos4x12 clocks: sclk_apll = 500000000, sclk_mpll = 800000000
    
    	sclk_epll = 96000000, sclk_vpll = 350000000, arm_clk = 1000000000
    
    sched_clock: 32 bits at 200 Hz, resolution 5000000ns, wraps every 10737418240000000ns
    
    Console: colour dummy device 80x30
    
    Calibrating delay loop... 1992.29 BogoMIPS (lpj=4980736)
    
    pid_max: default: 32768 minimum: 301
    
    Mount-cache hash table entries: 2048 (order: 1, 8192 bytes)
    
    Mountpoint-cache hash table entries: 2048 (order: 1, 8192 bytes)
    
    CPU: Testing write buffer coherency: ok
    
    missing device node for CPU 0
    
    missing device node for CPU 1
    
    missing device node for CPU 2
    
    missing device node for CPU 3
    
    CPU0: thread -1, cpu 0, socket 10, mpidr 80000a00
    
    Setting up static identity map for 0x403c0e10 - 0x403c0e68
    
    CPU1: Booted secondary processor
    
    CPU1: thread -1, cpu 1, socket 10, mpidr 80000a01
    
    CPU2: Booted secondary processor
    
    CPU2: thread -1, cpu 2, socket 10, mpidr 80000a02
    
    CPU3: Booted secondary processor
    
    CPU3: thread -1, cpu 3, socket 10, mpidr 80000a03
    
    Brought up 4 CPUs
    
    SMP: Total of 4 processors activated.
    
    CPU: All CPU(s) started in SVC mode.
    
    devtmpfs: initialized
    
    VFP support v0.3: implementor 41 architecture 3 part 30 variant 9 rev 4
    
    pinctrl core: initialized pinctrl subsystem
    
    regulator-dummy: no parameters
    
    NET: Registered protocol family 16
    
    DMA: preallocated 256 KiB pool for atomic coherent allocations
    
    S3C Power Management, Copyright 2004 Simtec Electronics
    
    EXYNOS4x12 PMU Initialize
    
    EXYNOS: Initializing architecture
    
    bio: create slab <bio-0> at 0
    
    VMEM_VDD_2.8V: 2800 mV 
    
    SCSI subsystem initialized
    
    usbcore: registered new interface driver usbfs
    
    usbcore: registered new interface driver hub
    
    usbcore: registered new device driver usb
    
    s3c-i2c 13860000.i2c: slave address 0x00
    
    s3c-i2c 13860000.i2c: bus frequency set to 19 KHz
    
    sec_pmic 0-0066: No interrupt specified, no interrupts
    
    VDD_ALIVE: failed to apply 1100000uV constraint
    
    s5m8767-pmic s5m8767-pmic: regulator init failed for 0
    
    s3c-i2c 13860000.i2c: i2c-0: S3C I2C adapter
    
    Switched to clocksource mct-frc
    
    NET: Registered protocol family 2
    
    TCP established hash table entries: 8192 (order: 3, 32768 bytes)
    
    TCP bind hash table entries: 8192 (order: 5, 163840 bytes)
    
    TCP: Hash tables configured (established 8192 bind 8192)
    
    TCP: reno registered
    
    UDP hash table entries: 512 (order: 2, 24576 bytes)
    
    UDP-Lite hash table entries: 512 (order: 2, 24576 bytes)
    
    NET: Registered protocol family 1
    
    RPC: Registered named UNIX socket transport module.
    
    RPC: Registered udp transport module.
    
    RPC: Registered tcp transport module.
    
    RPC: Registered tcp NFSv4.1 backchannel transport module.
    
    futex hash table entries: 1024 (order: 4, 65536 bytes)
    
    bounce pool size: 64 pages
    
    ROMFS MTD (C) 2007 Red Hat, Inc.
    
    msgmni has been set to 1458
    
    io scheduler noop registered
    
    io scheduler deadline registered
    
    io scheduler cfq registered (default)
    
    dma-pl330 12680000.pdma: Loaded driver for PL330 DMAC-1315632
    
    dma-pl330 12680000.pdma: 	DBUFF-32x4bytes Num_Chans-8 Num_Peri-32 Num_Events-32
    
    dma-pl330 12690000.pdma: Loaded driver for PL330 DMAC-1315632
    
    dma-pl330 12690000.pdma: 	DBUFF-32x4bytes Num_Chans-8 Num_Peri-32 Num_Events-32
    
    dma-pl330 12850000.mdma: Loaded driver for PL330 DMAC-1315632
    
    dma-pl330 12850000.mdma: 	DBUFF-64x8bytes Num_Chans-8 Num_Peri-1 Num_Events-32
    
    Serial: 8250/16550 driver, 4 ports, IRQ sharing disabled
    
    13800000.serial: ttySAC0 at MMIO 0x13800000 (irq = 84, base_baud = 0) is a S3C6400/10
    
    13810000.serial: ttySAC1 at MMIO 0x13810000 (irq = 85, base_baud = 0) is a S3C6400/10
    
    13820000.serial: ttySAC2 at MMIO 0x13820000 (irq = 86, base_baud = 0) is a S3C6400/10
    
    console [ttySAC2] enabled
    
    13830000.serial: ttySAC3 at MMIO 0x13830000 (irq = 87, base_baud = 0) is a S3C6400/10
    
    brd: module loaded
    
    loop: module loaded
    
    dm9000 5000000.ethernet: read wrong id 0x01010101
    
    eth0: dm9000a at f0076000,f0078004 IRQ 167 MAC: 00:0a:2d:a6:55:a2 (platform data)
    
    usbcore: registered new interface driver asix
    
    usbcore: registered new interface driver ax88179_178a
    
    usbcore: registered new interface driver cdc_ether
    
    usbcore: registered new interface driver smsc75xx
    
    usbcore: registered new interface driver smsc95xx
    
    usbcore: registered new interface driver net1080
    
    usbcore: registered new interface driver cdc_subset
    
    usbcore: registered new interface driver zaurus
    
    usbcore: registered new interface driver cdc_ncm
    
    ehci_hcd: USB 2.0 'Enhanced' Host Controller (EHCI) Driver
    
    ehci-exynos: EHCI EXYNOS driver
    
    usbcore: registered new interface driver usb-storage
    
    mousedev: PS/2 mouse device common for all mice
    
    input: 100a0000.keypad as /devices/100a0000.keypad/input/input0
    
    device-mapper: ioctl: 4.27.0-ioctl (2013-10-30) initialised: dm-devel@redhat.com
    
    sdhci: Secure Digital Host Controller Interface driver
    
    sdhci: Copyright(c) Pierre Ossman
    
    s3c-sdhci 12530000.sdhci: clock source 2: mmc_busclk.2 (40000000 Hz)
    
    mmc0: no vqmmc regulator found
    
    mmc0: SDHCI controller on samsung-hsmmc [12530000.sdhci] using ADMA
    
    Synopsys Designware Multimedia Card Interface Driver
    
    dwmmc_exynos 12550000.mmc: no vmmc regulator found: -19
    
    dwmmc_exynos 12550000.mmc: Using internal DMA controller.
    
    dwmmc_exynos 12550000.mmc: Version ID is 240a
    
    dwmmc_exynos 12550000.mmc: DW MMC controller at irq 109, 32 bit host data width, 128 deep fifo
    
    dwmmc_exynos 12550000.mmc: 1 slots initialized
    
    usbcore: registered new interface driver usbhid
    
    usbhid: USB HID core driver
    
    TCP: cubic registered
    
    NET: Registered protocol family 17
    
    NET: Registered protocol family 15
    
    Registering SWP/SWPB emulation handler
    
    VMEM_VDD_2.8V: disabling
    
    regulator-dummy: disabling
    
    drivers/rtc/hctosys.c: unable to open rtc device (rtc0)
    
    mmc1: BKOPS_EN bit is not set
    
    dm9000 5000000.ethernet eth0: link down
    
    mmc_host mmc1: Bus speed (slot 0) = 50000000Hz (slot req 52000000Hz, actual 50000000HZ div = 0)
    
    mmc_host mmc1: Bus speed (slot 0) = 100000000Hz (slot req 52000000Hz, actual 50000000HZ div = 1)
    
    mmc1: new high speed DDR MMC card at address 0001
    
    mmcblk0: mmc1:0001 4YMD3R 3.64 GiB 
    
    mmcblk0boot0: mmc1:0001 4YMD3R partition 1 4.00 MiB
    
    mmcblk0boot1: mmc1:0001 4YMD3R partition 2 4.00 MiB
    
    mmcblk0rpmb: mmc1:0001 4YMD3R partition 3 512 KiB
    
     mmcblk0: p1 p2 p3 p4
    
     mmcblk0boot1: unknown partition table
    
     mmcblk0boot0: unknown partition table
    
    dm9000 5000000.ethernet eth0: link up, 100Mbps, full-duplex, lpa 0x45E1
    
    IP-Config: Guessing netmask 255.255.255.0
    
    IP-Config: Complete:
    
         device=eth0, hwaddr=00:0a:2d:a6:55:a2, ipaddr=192.168.9.9, mask=255.255.255.0, gw=255.255.255.255
    
         host=192.168.9.9, domain=, nis-domain=(none)
    
         bootserver=255.255.255.255, rootserver=192.168.9.120, rootpath=
    
    clk: Not disabling unused clocks
    
    VFS: Mounted root (nfs filesystem) on device 0:10.  /*挂载根文件系统(从 nfs filesystem知挂载的是NFS rootfs)
      也可挂载jffs2 ramdisk cramfs等格式rootfs 等               
          如果到这里启动失败,可能原因
          1. bootargs 参数设置用问题  ,如设置mtdblock2 写成了mtdblock3, 或路径,名称不对等
          2. 设为nfs挂载,验证rootfs内容有没问题
          3. 制作镜像过程有没问题 
          */			
    	
    devtmpfs: mounted
    
    Freeing unused kernel memory: 228K (c0530000 - c0569000)  	
    

    3.4根文件系统阶段(可运行应用程序)

    [root@farsight ]# ls
    a.out dev lib mnt root sys usr
    bin etc linuxrc proc sbin tmp var
    [root@farsight ]# ./a.out
    hello

    4.U-BOOT 移植方法

    善用对比软件Beyond

    1. 选择官方源码版本下载, 配置编译
      a. 指定交叉编译工具链
      b. 指定cpu 和board(参考最类似配置如origen)
      c. 编译
    2. 实现串口信息输出
      a. 跟踪运行路径(led点灯法)
      b. 串口输出(检查uart初始化相关部分代码 见lowlevel_init.s)
    3. 网卡移植(实现能用tftp nfs 方便开发调试)
      a. 寄存器地址
      b. 参数设置
    4. FLASH移植(实现能下载软件到FLASH,产品能离线运行)

    04Linux内核分析(Linux内核基本概念,Linux内核启动分析,Linux内核调试方法)

    1.Linux内核基本概念

    1.1Linux内核

    • 从技术上说 linux 是一个内核
    • “内核”指的是一个提供硬件抽象层、磁盘及文件系统控制、多任务等功能的系统软件。一个内核不是一套完整的操作系统。
    • 通常我们使用的 linux 系统是一个集 linux 内核、工具集、各种库、桌面管理器、应用程序等一体的一个发布包 (发行版)‏

    1.2主流的 Linux 发行版

    • Debian GNU/Linux
    • Red Hat Linux
    • Fedora Core
    • Ubuntu Linux
    • SUSE Linux
    • Gentoo Linux
    • Asianux
    • Slackware Linux
    • Turbo Linux
    • CentOS

    1.3Linux 内核的特性

    • 免费开源
    • 可以移植,支持的硬件平台广泛
      arm, i386, m68k, m32r,m68knommu, mips, ppc, s390, sh, sparc
    • 高可扩展性
    • 可剪裁、可扩展,可以运行在大型主机,也可以运行在个人计算机上
    • 高可靠性、稳定性
    • 稳定性是linux鲜明特点,安装了linux系统的主机,
      连续运行一年不宕机是很平常的事情
    • 超强的网络功能
    • 真正的多任务,多用户系统
    • 模块化设计
    • 模块可以动态加载,卸载,可以减少系统体积,同时可以用来解决冲突问题,模块调试

    1.4Linux内核版本

    目前linux系统采用 A.B.C.D 的版本号管理方式

    • A 表示linux的主版本号
    • B 表示linux的次版本号,B 为偶数表示稳定版本,奇数表示开发中的版本
    • C 表示linux的发行版本号
    • D 表示更新版本号
      主版本(X.Y)
      1.0 2.0 2.2 2.4 2.6 3.x

    Linux内核子系统

    • 进程管理
    • 内存管理
    • 文件系统
    • 网络协议
    • 设备管理

    linux系统不是正真的实时系统(采用时间片轮转的方式做的)
    美国军方的Vxwork是正真的实时系统(中断抢占)

    1.5Linux内核模块结构图

    在这里插入图片描述

    应用访问内核要通过系统调用
    内核访问硬件要通过映射

    2.linux内核编译(移植好的)

    2.1编译内核 make uImage

    先改makefile中的交叉编译工具

    linux@linux:~/linux-3.14-fs4412$ make uImage 
    CHK     include/config/kernel.release
    CHK     include/generated/uapi/linux/version.h
    CHK     include/generated/utsrelease.h
    make[1]: “include/generated/mach-types.h”是最新的。
    CALL    scripts/checksyscalls.sh
    CHK     include/generated/compile.h
    Kernel: arch/arm/boot/Image is ready
    Kernel: arch/arm/boot/zImage is ready
    Image arch/arm/boot/uImage is ready
    linux@linux:~/linux-3.14-fs4412$ 
    

    2.2编译设备树 make dtbs

    linux@linux:~/linux-3.14-fs4412$ make dtbs 
    DTC     arch/arm/boot/dts/exynos4210-origen.dtb
    DTC     arch/arm/boot/dts/exynos4210-smdkv310.dtb
    DTC     arch/arm/boot/dts/exynos4210-trats.dtb
    DTC     arch/arm/boot/dts/exynos4210-universal_c210.dtb
    DTC     arch/arm/boot/dts/exynos4412-odroidx.dtb
    DTC     arch/arm/boot/dts/exynos4412-origen.dtb
    DTC     arch/arm/boot/dts/exynos4412-fs4412.dtb
    DTC     arch/arm/boot/dts/exynos4412-smdk4412.dtb
    DTC     arch/arm/boot/dts/exynos4412-tiny4412.dtb
    DTC     arch/arm/boot/dts/exynos4412-trats2.dtb
    DTC     arch/arm/boot/dts/exynos5250-arndale.dtb
    DTC     arch/arm/boot/dts/exynos5250-smdk5250.dtb
    DTC     arch/arm/boot/dts/exynos5250-snow.dtb
    DTC     arch/arm/boot/dts/exynos5420-arndale-octa.dtb
    DTC     arch/arm/boot/dts/exynos5420-smdk5420.dtb
    DTC     arch/arm/boot/dts/exynos5440-sd5v1.dtb
    DTC     arch/arm/boot/dts/exynos5440-ssdk5440.dtb
    

    2.3Linux内核代码结构(1)

    在这里插入图片描述

    2.4Linux系统源代码目录结构(2)

    在这里插入图片描述

    Linux内核启动分析

    3.嵌入式系统启动信息分析

    3.1u-boot启动阶段

    U-Boot 2013.01 (Aug 24 2014 - 12:01:19) for FS4412
    CPU:	Exynos4412@1000MHz
    Board: FS4412
    DRAM:  1 GiB
    ……Loading: * ######################
    Starting kernel ...
    

    3.2linux内核启动阶段

    Booting Linux on physical CPU 0xa00
    Linux version 3.14.0 (david@ubuntu)
    CPU: ARMv7 Processor [413fc090] revision 0 (ARMv7), cr=10c5387d
    Machine model: Insignal Origen evaluation board based on Exynos4412
    IP-Config: Complete:
    VFS: Mounted root (nfs filesystem) on device 0:10
    

    3.3根文件系统阶段(可运行应用程序)

    [root@farsight ]# ls
    a.out    dev      lib      mnt      root     sys      usr
    bin      etc      linuxrc  proc     sbin     tmp      va
    

    3.4嵌入式系统 启动流程

    在这里插入图片描述

    //阶段一(汇编) 
    设置为SVC模式,关闭中断,MMU,看门狗
    基本硬件设备初始化  //初始化时钟,串口,flash,内存    
    自搬移到内存          
    设置好栈 跳转到C阶段
    //阶段二(C语言)
    大部分硬件初始化
    搬移内核到 内存
    运行内核
    

    3.5内核启动流程

    a. 自解压内核 decompess (arch/arm/boot/compressed/head.S)

    b. 运行内核汇编部分 head.S 入口stext (arch/arm/kernel/head.S)
    检测合法性(CPU 类型,机器类型)

    c. 运行内核C部分 start_kernel (init/main.c)
    CPU,机器参数的安装 setup_arch
    中断,定时,终端,内存等最基本的初始化
    创建核心进程 kernel_init运行,启动多任务调度

    d. 挂载rootfs

    e. 运行第一个应用程序init (一般是 linuxrc)
    在这里插入图片描述

    4.Linux内核调试方法

    4.1内核调试方法1:点灯法

    ldr r0, =0x11000c40 @GPK2_7 led2
    ldr r1, [r0]
    bic r1, r1, #0xf0000000
    orr r1, r1, #0x10000000
    str r1, [r0]
    
    ldr r0, =0x11000c44
    mov r1,#0xff
    str r1, [r0]
    

    4.2内核调试方法 2:printk打印输出信息

    打印函数

    puts   (内核解压前)
    printascii  (console初始化前)
    printk (内核解压后,信息输出显示是在 console 初始化之后)
    

    打印级别

    #define KERN_EMERG        "<0>"   	/* system is unusable           */
    #define KERN_ALERT        "<1>”     /* action must be taken immediately */
    #define KERN_CRIT         "<2>"   	/* critical conditions          */
    #define KERN_ERR          "<3>"   	/* error conditions         */
    #define KERN_WARNING      "<4>"   	/* warning conditions           */
    #define KERN_NOTICE       "<5>"     /* normal but significant condition */
    #define KERN_INFO         "<6>"   	/* informational            */
    #define KERN_DEBUG        "<7>"   	/* debug-level messages
    

    printk( KERN_INFO “ \n INFO Level \n”);

    通过proc在运行时查看和修改日志级别

    cat /proc/sys/kernel/printk            显示   4 4 1 7
    echo “7 4 1 7” > /proc/sys/kernel/printk  后 
    cat /proc/sys/kernel/printk            显示7 4 1 7
    

    4.3内核调试方法 3: OOP内核异常信息

    制造错误

    修改drivers/char/fs4412_led_drv.c
    在s5pv210_led_init函数中int  ret=0;下增加下面语句: int *ptr  =  NULL; *ptr  = 0xff;
    

    运行该内核报错

    [    1.165000] Unable to handle kernel NULL pointer dereference at virtual address 00000000
    [    1.170000] pgd = c0004000
    [    1.175000] [00000000] *pgd=00000000
    [    1.175000] Internal error: Oops: 805 [#1] PREEMPT SMP ARM
    [    1.180000] Modules linked in:
    [    1.185000] CPU: 0 PID: 1 Comm: swapper/0 Not tainted 3.14.0 #25
    [    1.190000] task: ee8a0000 ti: ee8a4000 task.ti: ee8a4000
    [    1.195000] PC is at s5pv210_led_init+0x18/0x180
    [    1.200000] LR is at do_one_initcall+0x30/0x144
    [    1.205000] pc : [<c024225c>]    lr : [<c00087b4>]    psr: 60000153
    [    1.205000] sp : ee8a5ef8  ip : c059afac  fp : 00000000
    [    1.215000] r10: c052d4fc  r9 : c0564b80  r8 : c0242244
    [    1.220000] r7 : c05a3400  r6 : c055134c  r5 : 00000000  r4 : ee8a4000
    [    1.230000] r3 : 00000055  r2 : c04c0430  r1 : 00000001  r0 : 1f400000
    [    1.235000] Flags: nZCv  IRQs on  FIQs off  Mode SVC_32  ISA ARM  Segment kernel
    [    1.245000] Control: 10c5387d  Table: 4000404a  DAC: 00000015
    [    1.250000] Process swapper/0 (pid: 1, stack limit = 0xee8a4240)
    [    1.255000] Stack: (0xee8a5ef8 to 0xee8a6000)
    

    找出错位置(arm-none-linux-gnueabi-addr2line)

    根据PC is at s5pv210_led_init+0x18/0x180 知道出错的函数是s5pv210_led_init
    根据pc : [<c024225c>]  知道出错的位置
    #arm-none-linux-gnueabi-addr2line c024225c -e vmlinux -f   在源码中会显示具体出错的位置

    05Linux内核移植及网卡移植

    1.Linux内核 配置编译

    1.1下载内核源码

    (谷歌搜索 linux-3.14.tar.xz ,会很快找到有许多内核版本的列表)

    1.2Linux系统中解压

    ( tar -xvf linux-3.14.tar.xz 注意不能在与window的共享目录解压)

    linux@linux:~$ ls
    deja-dup  develop    Downloads         gcc-4.6.4         linux-3.14.79      linux-5.1.8   Music   Pictures  sdfuse_q   u-boot-2013.01-fs4412         u-boot-fs4412.bin  Videos                未命名文件夹
    Desktop   Documents  examples.desktop  gcc-4.6.4.tar.xz  linux-3.14-fs4412  linux_kernel  myfifo  Public    Templates  u-boot-2013.01-fs4412.tar.gz  uImage             vmware-tools-distrib
    linux@linux:~$ cd linux-3.14.79/
    linux@linux:~/linux-3.14.79$ ls
    arch   COPYING  crypto         drivers   fs       init  Kbuild   kernel  MAINTAINERS  mm               modules.order   net     REPORTING-BUGS  scripts   sound       tools  virt     vmlinux.o
    block  CREDITS  Documentation  firmware  include  ipc   Kconfig  lib     Makefile     modules.builtin  Module.symvers  README  samples         security  System.map  usr    vmlinux
    linux@linux:~/linux-3.14.79$ 
    

    1.3修改Makefile指定交叉编译工具链

    导入配置 make exynos_defconfig

    (配置列表见 arch/arm/configs/ 找最类似的)
    在这里插入图片描述
    直接编译会报错,需要先选配
    在这里插入图片描述
    导入配置
    在这里插入图片描述
    导入配置,发现出错了,需要在Makefile中修改交叉编译工具链
    在这里插入图片描述
    再次导入配置
    在这里插入图片描述

    1.4配置内核 make menuconfig

    编译内核之前需要激活配置

    linux@linux:~/linux-3.14.79$ make menuconfig
     *** Unable to find the ncurses libraries or the
     *** required header files.
     *** 'make menuconfig' requires the ncurses libraries.
     *** 
     *** Install ncurses (ncurses-devel) and try again.
     *** 
    make[1]: *** [scripts/kconfig/dochecklxdialog] Error 1
    make: *** [menuconfig] Error 2
    

    激活时出错 Unable to find the ncurses libraries
    解决方法:

    linux@linux:~/linux-3.14.79$ sudo apt-get install ncurses-dev
    linux@linux:~/linux-3.14.79$ make menuconfig
    

    在这里插入图片描述

    1.5编译内核 make uImage

    linux@linux:~/linux-3.14.79$ make uImage
    

    出现如下信息表示编译成功

    linux@linux:~/linux-3.14.79$ make uImage -j2
    CHK     include/config/kernel.release
    CHK     include/generated/uapi/linux/version.h
    CHK     include/generated/utsrelease.h
    make[1]: “include/generated/mach-types.h”是最新的。
    CALL    scripts/checksyscalls.sh
    CHK     include/generated/compile.h
    Kernel: arch/arm/boot/Image is ready
    Kernel: arch/arm/boot/zImage is ready
    Image arch/arm/boot/uImage is ready
    linux@linux:~/linux-3.14.79$ 
    

    1.6编译设备树 make dtbs

    linux@linux:~/linux-3.14.79$ make dtbs
    

    1.7网卡移植

    开发板上电重启,内核启动以后,卡在了 Starting kernel …

    在这里插入图片描述
    原因:
    因为原来的uboot里面没有电源管理单元的驱动,所以导致起不来。需要更换uboot ,现在的uboot是有电源管理驱动,可以解决卡在starting kernel的问题。

    更换uboot之后重新上电,内核启动以后,发现内核有崩溃信息

    在这里插入图片描述

    出错分析

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

    1. 开发板启动后,BootLoader运行,tftp下载内核,下载内核成功,通过内核挂载根文件系统
    2. uboot环境变量里有个参数bootargs(启动参数),uboot在bootm启动内核之后,会把bootargs传递给内核
    3. 内核通过bootargs知道根文件系统从哪里挂载(在远程的某台电脑上)
    4. 根文件系统是由内核挂载的,内核挂载必须通过网线来进行
    5. 开发板上的网卡,和三星官方发布的demo板(origen板)的网卡不一样,所以需要对网卡部分作出修改

    2.网卡移植—平台无关

    2.1配置内核支持网络

       $ make menuconfig
    

    配置网络协议支持TCP/IP

        [*] Networking support   --->     //注意要先输入y  选择该菜单,再按enter键,才能看到下面的选项
         	Networking options  ---> 
                    <*> Packet socket
                    <*> Unix domain sockets
    	            [*] TCP/IP networking
                   	[*]   IP: kernel level autoconfiguration
                   	[*]     IP: BOOTP support   
    

    配置支持网络文件系统 NFS

       File systems  --->   
       		[*] Network File Systems  --->
         		   	<*>   NFS client support
        		   	<*>     NFS client support for NFS version 2
                   	[*]     NFS client support for NFS version 3
                 	[*]     NFS client support for the NFSv3 
                            ACL protocol extension
                	[*]   Root file system on NFS    
    

    配置支持dm9000网卡驱动

    Device Drivers  --->
                [*] Network device support  --->
                	[*]   Ethernet driver support  --->
              			 <*>   DM9000 support       (网卡驱动里面可以只选择这个,把其他的都去掉)
    

    网卡移植—平台相关

    2.2置设备树描述网卡和CPU的链接情况

    $ vim arch/arm/boot/dts/exynos4412-origen.dts  在 regulators 前添加下面代码
    
    srom-cs1@5000000 {
        compatible = "simple-bus";
        #address-cells = <1>;
        #size-cells = <1>;
        reg = <0x5000000 0x1000000>;    对应芯片手册 3 Memory Map 的0x0500_0000  和 16 MB 		
        ranges;
    
        ethernet@5000000 {
             compatible = "davicom,dm9000";  内核通过该名字来匹配驱动
             reg = <0x5000000 0x2 0x5000004 0x2>;  寄存器地址和数据宽度
             interrupt-parent = <&gpx0>;   继承于 中断控制器gpx0
                interrupts = <6 4>; 6  对应中断源 DM9000_IRQ -> XEINT6 。4对应 active high level-sensitive 	     							
                davicom,no-eeprom;
             mac-address = [00 0a 2d a6 55 a2];
        };
    };
    

     

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

    2.3修改文件driver/clk/clk.c

    static bool clk_ignore_unused;
    

    改为

    static bool clk_ignore_unused = true;      //意思是忽略掉没有使用的时钟
    

    在这里插入图片描述
    修改好后,开发板上电重启
    make uImage -j2表示双线程编译,加快编译时间
    移植成功
    在这里插入图片描述

    3.CPU与设备连接描述 - 设备树DeviceTree

    1. Device Tree是描述硬件信息的数据结构
      用于管理 硬件拓扑和硬件资源信息。
      Device Tree由一系列被命名的结点(node)和属性(property)组成,而结点本身可包含子结点。
      所谓属性,其实就是成对出现的name和value。
    2. 帮助
      百度:linux Device Tree 详解
      官网:http://www.devicetree.org 和 http://elinux.org/Device_Tree
      源码实例:
      说明: Documentation/devicetree/bindings/arm
      源码: arch/arm/boot/dts/exynos4412-origen.dts

    3.1网卡对应的CPU内部总线节点的描述

    查看原理图,找出网卡片选信号控制I/O

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

    根据控制I/O,产看芯片手册

    在这里插入图片描述
    最后可以找出使能1对应的是bank1
    在这里插入图片描述

    • 所以地址就是0x5000000,长度就是0x6000000-0x5000000=0x1000000

    3.2网卡节点的描述

    在这里插入图片描述
    查看官方给的案例
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    4.CPU与设备连接描述 - 平台设备

    在内核里有一个结构“struct machine_desc”,内核用这个结构表示一个实际存在的板子,而针对每个板子都会有一个文件定义这个结构体,这个文件叫平台代码;
    如:arch/arm/mach-s5pv21/mach-smdkv210.c(新版本内核中没有基于Exynos4412的平台代码,这里以s5pv210为例)

    MACHINE_START(SMDKV210, "SMDKV210")
    		/* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
    		.atag_offset	= 0x100,
    		.init_irq	= s5pv210_init_irq,
    		.map_io	= smdkv210_map_io,
    		.init_machine	= smdkv210_machine_init,
    		.init_time	= samsung_timer_init,
    		.restart	= s5pv210_restart,
    		.reserve	= &smdkv210_reserve,
    MACHINE_END

    06第三方驱动移植(驱动编译进内核Makefile,图像化配置Kconfig,驱动模块,黑白盒对比)

    1.第三方驱动 黑盒移植

    在这里插入图片描述

    2.驱动编译进内核Makefile

    1、首先找内核中是否已经支持设备的驱动  选配
    2、内核中没有的驱动移植进来 --第三方驱动移植
    
    将第三方驱动代码放到linux源码树中的driver目录中
    修改 Makefile Kconfig(界面配置) 
    修改过的和新添加的代码会重新编译
    程序需要在板子上运行 就需要使用交叉编译工具编译
    mknod /dev/led c或者b  主设备号  次设备号
    

    2.1选择驱动存放目录 (或任意目录)

    拷贝LED驱动程序至drivers目录
    LED属于字符设备,所以放在drivers/char/目录下
    在这里插入图片描述

    2.2改Makefile让驱动编译进内核(同步修改,对应目录下的Makefile)

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

    2.3改Kconfig (界面可配置)

    测试驱动

    烧写镜像至开发板
    在这里插入图片描述
    驱动程序测试代码

    #include <stdio.h>
    #include <fcntl.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include <sys/ioctl.h>
    
    #define LED_MAGIC 'L'
    #define LED_ON  _IOW(LED_MAGIC, 1, int)
    #define LED_OFF _IOW(LED_MAGIC, 2, int)
    
    int main(int argc, char **argv)
    {
    	int fd;
    	
    	fd = open("/dev/led", O_RDWR);
    	if (fd < 0) {
    		perror("open");
    		exit(1);
    	}
    	
    	printf("open led ok\n");
    	
    	//实现LED灯闪烁
    	while(1)
    	{
    	  ioctl(fd, LED_ON); //点亮灯
    	  usleep(100000);
    	  ioctl(fd, LED_OFF); //灭灯
    	  usleep(100000);
    	}
    	
    	return 0;
    }
    

    2.4编译并拷贝至根文件系统
    在这里插入图片描述
    2.5在开发板上运行该测试程序
    在这里插入图片描述
    分析这个打印信息的来源
    在这里插入图片描述
    3.需要创建设备文件

    3.1创建设备文件

    在这里插入图片描述

    mknod /dev/led c 501 0
    

    在这里插入图片描述
    创建好设备文件后,再运行测试程序,就可以看到LED灯在闪烁了

    4.图形化配置Kconfig

    make menuconfig、Makefile、Kconfig、.config 三者的关系

    menuconfig 运行的时候,会读取内核下面所有的Kconfig,根据Kconfig生成对应的图形界面
    Makfile 具体编译文件
    Kconfig 选配,生成图形化界面(在界面中显示一些选项)
    	在Kconfig中添加一个灯的选项
    	界面修改好了, 还需要再次修改 Makfile
    	[] 只有两种选项编译(y)或者不编译(n)  
    	<> 三种选项 编译(y)、不编译(n)或者编译成模块(m)
    	obj-y obj-n obj-$(CONFIG_XXX)
    方便驱动管理
    

     

    4.1配置Kconfig

    在Kconfig中添加一个灯的选项

    在这里插入图片描述

    linux@linux:~/linux-3.14.79$ make menuconfig
    

    可以看到图形界面中多了一个对应的选项
    在这里插入图片描述

    修改Makefile

    在这里插入图片描述

    在图形界面选择不编译LED驱动,看是否成功

    在这里插入图片描述
    没有编译LED驱动

    在这里插入图片描述

    开发板上电重启,也可以测试出LED驱动没有被编译进来

    在这里插入图片描述

    5.编译驱动为独立的模块

    驱动模块学习 详细视频
    linux 内核模块 http://www.makeru.com.cn/live/1392_586.html
    驱动初级也会详细讲解

    5.1C程序代码编写

    创建驱动程序的文件夹,将文件拷贝进来,并为之编写Makfile
    在这里插入图片描述

    5.2Makefile 编写

    在这里插入图片描述

    5.3编译出 ko 模块

    • make之后,会自动跳到内核里面,借用内核的Makefile把当前驱动程序编译成ko文件
    • 在这里插入图片描述

    配置为模块方式

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

    5.4make modules 编译所有的模块

    在这里插入图片描述

    5.5在linux运行时,可以装载和卸载模块

    拷贝LED驱动模块到根文件系统

    在这里插入图片描述

    通过 手动加载模块 insmod *.ko

    卸载是rmmod
    在这里插入图片描述

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

    在这里插入图片描述

    运行测试驱动的应用程序

    在这里插入图片描述

    6.白盒移植

    1. 打印跟踪
      所谓白盒移植,就是在驱动代码中加一些打印信息(printk)来跟踪
    2. 驱动框架
      要加打印信息,就要熟悉框架是怎样的

    黑白盒对比

    黑盒移植
    	两种方式
    		1. 驱动编译进内核
    			选则源码目录
    			修改Makefile
    			修改Kconfig
    			
    		2. 将驱动编译成独立的模块
    			配置为模块方式 通过修改Kconfig
    			使用make modules 编译为模块
    			装载模块 insmod xxx.ko
    			创建设备结点 mknod /dev/xxx c xx xx
    			运行测试驱动的应用程序
    白盒移植
    	需要阅读阅读源码,熟悉驱动框架
    	1. 字符设备   2. 平台设备
    		字符设备框架
    								application
    		User Mode					||
    									\/
    		--------------------------------------------------	
    							System Call Interface
    									||
    		Kernel Mode				\/
    							Virture File System(VFS)
    								|      |     |
    						   Character Block  Network
    								|      |     |
    							Device interface
    									||
    									\/
    		-------------------------------------------------
    		Hardware		Physical Device (Hardware)
    

     

    驱动框架

    在这里插入图片描述

    字符设备框架

    在这里插入图片描述

    字符设备引入

    1.一切设备皆文件
    	对设备的操作的就是 对设备文件的 read write
    2. open read write ioctl 
    3. 将设备进行编号 设备号(主次设备号组成)
    

     

    字符设备驱动相关

    1. 注册获取设备号
    2. 初始化设备
    3. 操作设备 file_operations		-- open release read write ioctl...
    4. 两个宏定义 module_init  module_exit  两个命令 insmod   rmmod
    5. 注册设备号  register_chrdev_region
    6. cdev_init 初始化字符设备
    7. cdev_add 添加字符设备到系统
    
    驱动是被动调用的,是被应用程序触发的 
    应用程序的 open  调用到驱动的file_operations 的 open
    应用程序的 read  调用到驱动的file_operations 的 read
    应用程序的 write 调用到驱动的file_operations 的 write
    应用程序的 ioctl 调用到驱动的file_operations 的 ioctl
    应用程序的 close 调用到驱动的file_operations 的 release
    

     

    LED驱动代码—fs4412_led_drv.c

    #include <linux/kernel.h>
    #include <linux/module.h>
    #include <linux/fs.h>	
    #include <linux/cdev.h>
    #include <asm/io.h>
    
    
    #define LED_MAGIC 'L'
    #define LED_ON  _IOW(LED_MAGIC, 1, int)
    #define LED_OFF _IOW(LED_MAGIC, 2, int)
    
    #define LED_MA   501
    #define LED_MI    0
    #define LED_NUM   1
    
    #define LED_CON 0x11000C20
    #define LED_DAT 0x11000C24
    
    struct cdev cdev;
    
    unsigned int *ledcon;
    unsigned int *leddat;
    
    int led_open (struct inode *inode, struct file *file)
    {
      printk("led_open\n");
    
      ledcon = ioremap(LED_CON, 4);  	//内核访问硬件需要地址映射
      if(ledcon == NULL)
      {
    	  printk("ioremap LED_CON error\n");
          return -1;
      }
      writel(0x01, ledcon);  //设置LED3 GPX1_0 为输出模式
    
     leddat = ioremap(LED_DAT, 4);  	//内核访问硬件需要地址映射
     if(leddat == NULL)
     {
    	 printk("ioremap LED_DAT error\n");
    	 return -1;
     }
     writel(1, leddat);	//设置LED3 GPX1_0 输出高电平
      
      return 0;
    }
    
    int led_release(struct inode *inode, struct file *file)
    {
       printk("led_close\n");
       return 0;
    }
    
    long led_ioctl(struct file *file, unsigned int cmd, unsigned long args)
    {
      switch(cmd)
      {
      case  LED_ON:
    	   printk("led on ..\n");
           writel(1, leddat);	//设置LED3 GPX1_0 输出高电平
      	   break;
      case  LED_OFF:
    	   printk("led off ..\n");  	
           writel(0, leddat);	//设置LED3 GPX1_0 输出高电平	  
    	   break;
      default:
      	   printk("no command\n");
      	   break;
      }
      return 0;
    }
    
    struct file_operations led_fops = { //文件操作
    	.owner = THIS_MODULE,
        .open = led_open,
        .release =led_release,
        .unlocked_ioctl = led_ioctl,
    };
    
    static led_init(void)
    {
       int ret;
       dev_t devno = MKDEV(LED_MA, LED_MI); 
       ret= register_chrdev_region(devno, LED_NUM, "newled");  //注册设备号
       if(ret)
       {
    	   printk("register_chrdev_region error\n");
           return -1;
       }
    
       cdev_init(&cdev, &led_fops);           //初始化字符设备
       ret = cdev_add(&cdev, devno, LED_NUM); //添加字符设备到系统中
       if (ret < 0) {
    	   printk("cdev_add error\n");
    	   return -1;
       }
    
    	printk("Led init  5    \n");
    	return 0;
    }
    
    static void led_exit(void)
    {
    	dev_t devno = MKDEV(LED_MA, LED_MI);
    	cdev_del(&cdev);
    	unregister_chrdev_region(devno, LED_NUM);  //取消注册	
    	printk("Led exit\n");	
    }
    
    module_init(led_init);   		//模块加载入口  对应命令insmod
    module_exit(led_exit); 			//模块卸载入口  对应命令rmmod
    MODULE_LICENSE("Dual BSD/GPL"); //免费开源声明
    

     

    平台设备框架

    在这里插入图片描述

    平台设备引入

    在这里插入图片描述
    将驱动中的硬件信息剥离出来,放到设备树文件中

    1. 寄存器的地址值是根据芯片手册 和原理图找到的
    2. 对寄存器地址内容操作不能直接使用物理地址,需要ioremap
    3. ioremap 将物理地址 映射到虚拟地址
    4. platform 用于将硬件信息 和驱动代码做分离
    5. 通过名字匹配,匹配成功执行 probe函数
    6. 驱动通过 platform_get_resource 获取硬件设备资源
    7. 作用 容易维护

    07植根文件系统制作(根文件系统基本概念,根文件系统设备,访问根文件系统制作)

    1.根文件系统基本概念

    1.1什么是根文件系统?

    • 根文件系统(root filesystem)是存放运行、维护系统所必须的各种工具软件、库文件、脚本、配置文件和其他特殊文件的地方,也可以安装各种软件包。
    • 整个系统起来之后运行的第一个文件系统
    • 根文件系统下还可以搭建其他的文件系统

    1.2根文件系统主要目录结构

    在这里插入图片描述

    1.3程序文件的放置

    程序文件目录

    /bin: 普通用户和root用户都能执行的基本程序

      ping, mknod, mount, tar, grep, gzip, etc
    

    /sbin: root用户能执行的基本程序

      int, insmod, route, mkfs, rmmod, ifconfig
    

    /usr/bin: 更多非必须的用户程序

      autorun, bibtex, latex, biff, ftp, wc, whereis, whoami
    

    /usr/sbin: 更多非必须的root工具程序

      automount, httpd, in.telnetd, in.talkd, sendmail
    

    1.4定制应用程序

    配置基本的linux命令(嵌入式linux通过busybox制作)

      cat, chmod, chown, cp, chroot, copi, date, dd, df, dmesg, dos2unix, du, echo, env, expr,  find, grep, gunzip, gzip, halt, id, ifconfig, init, insmod等等
    

    配置用户自己的应用
    桌面管理器等等

    1.5库文件的放置

    /lib: 系统和运行基本命令时需要的动态库文件
    /usr/lib:所有的其他库
    /usr/lib/xxx: 一些工具包的私有库
    如:/usr/lib/perl5

    2.Linux 设备文件

    • Linux 系统中所有的对象(包括设备)都是以文件的形式体现的
    • Linux系统中,所有的设备文件(如:设备节点),通常放到 /dev下
    • 嵌入式系统中只需要创建必须的设备节点即可

    举例

    2.1字符设备举例

    ls –l /dev/  “c” 指明该设备节点是字符设备

    crw-rw---- 1 root uucp  4,    64 Feb 23 2004 /dev/ttyS0      //4表示主设备号,64表示次设备号
    crw--w---- 1 jdoe tty    136, 1   Feb 23 2004 /dev/pts/1
    crw-------- 1 root root   13,   32 Feb 23 2004 /dev/input/mouse0
    crw-rw-rw 1 root root   1,    3    Feb 23 2004 /dev/null
    

    典型设备
    keyboards, mice, parallel port, IrDA, Bluetooth port, consoles, terminals, sound, video…

    2.2块设备举例

    “b” 指明该设备节点是块设备 (ls -l)

    brw-rw--- 1 root disk      3, 1 Feb 23 2004 hda1
    brw-rw--- 1 jdoe floppy  2, 0 Feb 23 2004 fd0
    brw-rw--- 1 root disk      7, 0 Feb 23 2004 loop0
    brw-rw--- 1 root disk      1, 1 Feb 23 2004 ram1
    brw------- 1 root root      8, 1 Feb 23 2004 sda1
    

    典型块设备

    磁盘, ramdisk,SD,U盘等等
    

    2.3设备的主设备号次设备号

    • Linux系统是通过主设备号和次设备号来区分设备的
    • 主设备号: (major)
      内核用来区分哪类设备
    • 次设备号: (minor)
      区分某类设备中的哪个设备
    • 内核中的相关文档 Documentation/devices.txt
    •  

    3.创建设备节点

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

    • 创建设备文件的一般语法:

        $ mknod /dev/<device> [c|b] <major> <minor>
      

    例如:

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

    基本的设备节点

    在这里插入图片描述

    4.Linux系统的引导过程

    在这里插入图片描述

    制作根文件系统   

    5.文件系统制作步骤

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

    6.BusyBox项目构建系统命令

    1. BusyBox 项目是由Bruce Perens in 在1996创建的
      http://www.busybox.net/
      BusyBox 是在 GNU GPL 许可协议下发行的开源软件
    2. 享有“嵌入式Linux的瑞士军刀”美誉,Erik Andersen先生维护;
    3. Busybox是一个UNIX系统工具集,它将很多普通的UNIX工具集成到一个很小的可执行文件中,为普通用户提供大多数常用的命令;
    4. BusyBox常用于制作linux命令 主要指令包括
      cat, chmod, chown, cp, chroot, copi, date, dd, df, dmesg, dos2unix, du, echo, env, expr, find, grep, gunzip, gzip, halt, id, ifconfig, init, insmod, etc

    7.BusyBox工具安装

    linux@linux:~$ cp /mnt/hgfs/Linuxsharexiaomei/busybox-1.22.1.tar.bz2 .
    linux@linux:~$ tar -vxf busybox-1.22.1.tar.bz2 
    linux@linux:~$ cd busybox-1.22.1/
    

    制作根文件系统的内容

    $ make menuconfig
        Busybox Settings ---> 
    	Build Options --->
    		[*] Build BusyBox as a static binary (no shared libs)
    		(arm-none-linux-gnueabi-) Cross Compiler prefix   注意 一定要指定交叉编译工具
    $ make
    $ file busybox   确认编译生成的是 ARM 平台的(显示为ELF 32-bit LSB executable, ARM)
    

     

    在这里插入图片描述

    $ make  install   安装(默认安装路径为_install)
    

    在这里插入图片描述

    $ cd _install
    $  ls
          bin  linuxrc  sbin  usr
    $ mkdir  dev  etc  mnt  proc  var  tmp  sys  root       创建需要的目录
    

    在这里插入图片描述

    $ cp  ~/gcc-4.6.4/arm-arm1176jzfssf-linux-gnueabi/lib/  .  -a      注意是lib/ 
    $ du -mh lib     查看lib库的大小
    $ rm  lib/*.a     裁剪,删除掉静态库文件  
    $ arm-none-linux-gnueabi-strip  lib   裁剪掉调试信息   not recognized  有些库是不能strip的 忽略掉
    $ sudo rm  lib/libstdc++*   删除不需要的库,确保所有库大小不超过4M  
    $ du -mh lib    查看lib库的大小  可能 显示3.4M lib   (这里确保小于 8M) 	
    

    在这里插入图片描述

    $ cp /nfs/rootfs/etc   -rf   .      拷入成熟的参考配置 
    

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

    $sudo mknod   dev/console  c  5  1      必须要有  console设备节点
    

    在这里插入图片描述

    8.测试

    看新的根文件系统能否正常挂载到开发板

    linux@linux:~/busybox-1.22.1$ mv /nfs/rootfs /nfs/rootfs.ok      把原有的根文件系统备份一下
    linux@linux:~/busybox-1.22.1$ sudo cp -rf _install /nfs/rootfs      把新的根文件系统拷贝过去(改名rootfs)
    

    配置文件一

    文件 /etc/inittab

    #this is run first except when booting in single-user mode.
    :: sysinit:/etc/init.d/rcS  指定系统初始化脚本是rcS 也可指定别的名字,但习惯用rcS
    # /bin/sh invocations on selected ttys
    # start an "askfirst" shell on the console (whatever that may be)
    ::askfirst:-/bin/sh    指定初始的控制台(启动后进入# 状态)  
    ::restart:/sbin/init
    ::ctrlaltdel:/sbin/reboot
    

    文件 /etc/init.d/rcS(启动脚本)

    #!/bin/sh
    # This is the first script called by init process
    /bin/mount  -a                                 mount all stuff from /etc/fstab  
    /etc/init.d/rc.local                           扩展子脚本
    echo  /sbin/mdev  >  /proc/sys/kernel/hotplug  设置系统的hotplug程序为mdev
    /sbin/mdev  -s                                 
    ./app.exe   //让脚本自动运行你的程序 
    

    配置文件二

    文件 /etc/fstab

    #device     mount-point     type        options        dump     fsck order
    proc          /proc        proc        defaults         0             0
    tmpfs         /tmp          tmpfs       defaults         0             0
    sysfs          /sys         sysfs       defaults         0             0
    tmpfs         /dev          tmpfs       defaults         0             0   
    

    文件 /etc/profile

    #!/bin/sh
    export HOSTNAME=farsight
    export USER=root
    export HOME=root
    export PS1="[$USER@$HOSTNAME \W]\# "       终端前的提示符
    PATH=/bin:/sbin:/usr/bin:/usr/sbin
    LD_LIBRARY_PATH=/lib:/usr/lib:$LD_LIBRARY_PATH
    export PATH  LD_LIBRARY_PATH 
    

    测试rootfs内容正确性

    $ cd /nfs
    $ mkdir rootfs
    $ cp  _install/*   rootfs   –a                        
    $ chmod 777 /nfs/rootfs/		
    

    NFS能挂载成功表示根文件系统 内容基本正确

    制作需要的rootfs类型的格式

    在这里插入图片描述

    不同根文件系统详解

    nfs rootfs

    是网络文件文件系统,通过网线远程挂载一个文件系统,文件系统在远程的电脑上。最大的好处是同步,主要用于开发调试

    CRAMFS

    只读,不能写。安全性高,某些区域的数据不能改,就可以定义为CRAMFS。

    JFFS2和YAFFS2

    可读,可写,针对都是flash。JFFS2在小型应用系统用的比较多。JFFS2有一个特点:是一个日志文件系统,用的过程中可以随时掉电。YAFFS2只能针对Nand flash,手机中用的最多的是Nand flash,文件系统就是YAFFS2

    EXT2 over RAM disk

    把一块内存虚拟成为一个磁盘。内存只能按地址空间像一个buffer一样访问,当应用产品内存比较大而flash比较小时,就可以按这种格式把一块内存虚拟成为一个磁盘

    制做EXT2 over RAM disk文件系统

    制作一个大小为8M的镜像

    linux@linux:~$ dd if=/dev/zero of=ramdisk  bs=1k  count=8192
    
    if	:(input file)输入文件
    /dev/zero	:是一个虚拟的设备,从这个设备中读到的数据全是0
    of	:(output file)输出文件
    bs=1k count=8192: 单元大小是1k,数量是8k,就是8M大小
    

    在这里插入图片描述

    格式化这个镜像为EXT2

    linux@linux:~$ mkfs.ext2 -F ramdisk
    

    在这里插入图片描述

    在mount下面创建initrd目录作为挂载点

    linux@linux:~$ sudo mkdir /mnt/initrd
    

    将这个磁盘镜像文件挂载到/mnt/initrd下

    注意这里的ramdisk不能存放在rootfs目录中

    linux@linux:~$ sudo mount -t ext2 ramdisk /mnt/initrd
    

    在这里插入图片描述

    将我们的文件系统复制到ramdisk中

    将测试好的文件系统里的内容全部拷贝到/mnt/initrd目录下面

    linux@linux:~$ sudo cp /nfs/rootfs/* /mnt/initrd/ -a
    

    在这里插入图片描述

    卸载initrd

    linux@linux:~$ sudo umount /mnt/initrd
    

    在这里插入图片描述

    压缩ramdisk为ramdisk.gz并拷贝到/tftpboot下

    linux@linux:~$ gzip --best -c ramdisk > ramdisk.gz
    

    在这里插入图片描述

    格式化为uboot识别的格式,并拷贝到/tftpboot下

    linux@linux:~$ mkimage -n "ramdisk" -A arm -O linux -T ramdisk -C gzip -d ramdisk.gz ramdisk.img
    
    linux@linux:~$ cp ramdisk.img /tftpboot/
    

    在这里插入图片描述

    配置内核支持RAMDISK

    制作完ramdisk.img后,需配置内核支持RAMDISK作为启动文件系统

    make menuconfig
    
    	File systems  --->   
    		<*> Second extended fs support  
    	Device Drivers  --->        
    		SCSI device support  --->     
              	<*> SCSI disk support     
    		[*] Block devices  --->  
    			<*>   RAM block device support                                                   
    			(16)    Default number of RAM disks                                            
    			(8192)  Default RAM disk size (kbytes)  (修改为8M)
    	General setup  --->  
    		[*] Initial RAM filesystem and RAM disk (initramfs/initrd) support  
    

    重新编译内核,复制到/tftpboot

    在U-BOOT命令行重新设置启动参数

    在这里插入图片描述

    展开全文
  • 使用eabi版本有诸多优势,具体大家可以网上搜索,此文档以在ubuntu中安装arm-linux-gcc-4.5.1-v6-vfp-20120301为主要内容。 3.安装步骤 3.1 安装32位的库 sudo apt-get install libc6:i386 sudo apt-get ...

    安装arm-linux-gcc交叉编译器
    1、开发平台

    虚拟机:VMware 12

    操作系统:Ubuntu 14.04

    2.准备交叉编译工具包(arm-linux-gcc-4.5.1)

    编译uboot和linux kernel都需要gnu交叉工具链支持,这里使用友善之臂提供的arm-linux-gcc-4.5.1-v6-vfp-20120301版交叉编译工具。使用eabi版本有诸多优势,具体大家可以到网上搜索,此文档以在ubuntu中安装arm-linux-gcc-4.5.1-v6-vfp-20120301为主要内容。

    3.安装步骤

    3.1 安装32位的库

    sudo apt-get install libc6:i386
    
    sudo apt-get install lib32z1
    

    注意:在64位Linux安装arm-linux-gcc-4.5.1交叉编译器,要先安装32位的库(arm-linux-gcc-4.5.1-v6-vfp-20120301是在32位的Linux下编译的)

    3.2、Ubuntu14.04 64bit系统下安装标准的C开发环境

    sudo apt-get install gcc g++ libgcc1 libg++ make gdb

    或者 sudo apt-get install build-essential

    3.3、安装arm-linux-gcc-4.5.1-v6-vfp-20120301

    在/usr/local/文件夹下建立名为armtools的文件夹:

    $ sudo mkdir /usr/local/armtools
    

    通过共享文件夹或者samba的方式拷贝arm-linux-gcc-4.5.1-v6-vfp-20120301.tgz到/usr/local/ armtools/目录下;在/usr/local/ armtools/目录下解压arm-linux-gcc-4.5.1-v6-vfp-20120301.tgz:

    sudo tar –xvf arm-linux-gcc-4.5.1-v6-vfp-20120301.tgz
    

    3.4、修改环境变量,把交叉编译器的路径加入到PATH

    修改/etc/bash.bashrc文件(此文件只对当前用户适用)

    $sudo gedit /etc/bash.bashrc
    

    然后在文件的末尾空白处加入一下代码:

    Add ARM toolschain path

    if [ -d /usr/local/armtools/FriendlyARM/toolschain/4.5.1 ] ; then

    PATH=/usr/local/armtools/FriendlyARM/toolschain/4.5.1/bin:"${PATH}"

    fi

    3.5、使新的环境变量生效(不用重启电脑)

    $ source /etc/bash.bashrc
    

    3.6. 检查是否将路径加入到PATH:

    echoPATH
    

    若显示的内容中含有:/usr/local/armtools/FriendlyARM/toolschain/4.5.1/bin 说明已经将交叉编译器的路径加入PATH。

    至此,交叉编译环境安装完成。

    3.7. 测试是否安装成功

    $ arm-linux-gcc -v
    
    展开全文
  • elecfans.com-单片机从入门到精通系列讲座之单片机最小系统及IO应用,希望对初学者有帮助
  • java从入门到精通

    2018-02-03 10:15:00
    《Java从入门到精通(视频实战版)》一共分为5篇,循序渐进地讲述了Java语言的各项技术。第一篇Java技术入门使读者对Java语言有个初步的了解,为后面的深入学习奠定基础。第二篇面向对象技术是需要读者认真学习和体会...
  • ARM 嵌入式 Linux 系统开发从入门到精通
  • ARM 嵌入式 Linux 系统开发从入门到精通 第 1 章 嵌入式系统开发入门 第 2 章 交叉编译工具链的构建 第 3 章 嵌入式系统的 BOOTLOADER 第 4 章 嵌入式 LINUX 内核移植 第 5 章 ARM LINUX 驱动程序开发入门 第 6 章 ...
  • 德国倍福BECKHOFF嵌入式PC从入门到精通V26(1).pdf,兼容C++、C# ,可在Visual Studio开发环境下编程
  • BECKHOFF嵌入式PC从入门到精通V26
  • 压缩文件里面是百度网盘下载地址长期有效,这套视频是我之前学习的时候用的,现分享给爱学习的朋友。本想免积分,但网站最低要求1分。
  • 很详细也很基础的linux学习教程,很适合初学者的学习。
  • 涉及模拟电路,数字电路,C语言、计算机组成原理,微机控制技术,网络技术,数据结构等课程,很多初学者对嵌入式涉及的这么多课程和知识点,往往不知道何处下手开始学习嵌入式。推荐一套linux嵌入式arm开发教程,...
    [size=small]linux嵌入式开发的简介:
    
    嵌入式开发不同于普通的纯软件开发,它是综合了计算机软、硬件的一门综合学科,涉及模拟电路,数字电路,C语言、计算机组成原理,微机控制技术,网络技术,数据结构等课程,很多初学者对嵌入式涉及的这么多课程和知识点,往往不知道从何处下手开始学习嵌入式。推荐一套linux嵌入式arm开发教程,课程采用理论教学与实验相结合的方式,软件与硬件相结合的方式,重点讲解嵌入式系统的开发的方法,系统地介绍嵌入式ARM程序开发技术。希望能够帮助大家少走些弯路。

    《linux嵌入式ARM系统实战开发(编程模型、指令系统、程序设计、混合编程、驱动开发)》
    适合人群:初级
    课时数量:70课时
    用到技术:ARM、UART、NandFlash
    涉及项目:万年历、看门狗定时器
    咨询qq:1821781423

    linux嵌入式开发从入门到精通
    学习目标:
    通过本课程的学习,可以掌握ARM开发环境的搭建、ARM的汇编程序设计、ARM的C程序设计、嵌入式硬件设计、ARM的裸板驱动设计等能力,引导学员进入嵌入式开发的精彩世界,为后续深入学习嵌入式Linux驱动编程打下坚实的硬件基础。

    视频课程亮点:
    本课程重点是给大家讲解嵌入式ARM的开发方法,采用理论与实践,硬件与软件相结合的方法。
    1、在每节开始之前先简单回顾上一节所讲的主要内容,并对本节所讲的内容先进行概述,讲解概念、技术要点,设计实现思路等内容,最后总结本次课程的要掌握的要点。
    2、每讲解一次理论课后都会讲解硬件原理图和实例代码,帮助理解理论知识,详细讲解代码如何实现的以及编程过程中注意的问题。
    linux嵌入式开发从入门到精通
    一、课程概要:

    第一阶段:嵌入式ARM体系结构
    第1讲ARM处理概述
    第2讲ARM体系结构

    第二阶段:嵌入式ARM编程模型

    第3讲ARM处理器编程模型-ARM处理器工作模式
    第4讲ARM处理器编程模型-ARM寄存器组织
    第5讲ARM处理器编程模型-ARM异常中断处理(上)
    第6讲ARM处理器编程模型-ARM异常中断处理(下)


    第三阶段:嵌入式ARM开发环境搭建

    第7讲ARM集成开发环境搭建-ADS1.2安装
    第8讲ARM集成开发环境搭建-JLINK配置软件安装
    第9讲ARM集成开发环境搭建-应用举例


    第四阶段:嵌入式ARM处理器指令系统

    第10讲ARM处理器指令系统-ARM指令集概述
    第11讲ARM处理器指令系统-ARM指令条件码
    第12讲ARM处理器指令系统-条件码实例分析
    第13讲ARM处理器指令系统-数据处理指令分析
    第14讲ARM处理器指令系统-算术运算指令分析
    第15讲ARM处理器指令系统-移位操作
    第16讲ARM处理器指令系统-算术运算指令实例分析
    第17讲ARM处理器指令系统-逻辑运算指令分析
    第18讲ARM处理器指令系统-灵活的第二源操作数分析
    第19讲ARM处理器指令系统-分支指令系统分析
    第20讲ARM处理器指令系统-汇编综合实例分析(1)
    第21讲ARM处理器指令系统-程序状态寄存器指令系统分析
    第22讲ARM处理器指令系统-加载存储指令系统分析
    第23讲ARM处理器指令系统-汇编综合实例分析(2)
    第24讲ARM处理器指令系统-汇编综合实例分析(3)
    第25讲ARM处理器指令系统-块数据传送指令系统分析
    第26讲ARM处理器寻址方式(上)
    第27讲ARM处理器寻址方式(下)


    第五阶段:嵌入式ARM汇编程序设计

    第28讲ARM处理器汇编程序设计-符号伪操作分析
    第29讲ARM处理器汇编程序设计-数据定义伪操作分析
    第30讲ARM处理器汇编程序设计-控制伪操作分析
    第31讲ARM处理器汇编程序设计-其它伪操作分析
    第32讲ARM处理器汇编程序设计-伪指令分析
    第33讲ARM处理器汇编程序设计-汇编程序格式分析


    第六阶段:嵌入式ARM汇编与C语言混合编程

    第34讲ARM处理器汇编程序设计-c语言和汇编混合编程(上)
    第35讲ARM处理器汇编程序设计-c语言和汇编混合编程(下)


    第七阶段:嵌入式ARM接口编程开发(ARM裸板驱动开发)

    第36讲ARM处理器接口编程-开发板原理图分析
    第37讲ARM处理器接口编程-GPIO原理分析
    第38讲ARM处理器接口编程-LED编程汇编语言程序实现
    第39讲ARM处理器接口编程-LED编程C语言实现
    第40讲ARM处理器接口编程-启动程序原理分析
    第41讲ARM处理器接口编程-系统时钟编程
    第42讲ARM处理器接口编程-存储器接口编程
    第43讲ARM处理器接口编程-系统堆栈初始化分析
    第44讲ARM处理器接口编程-系统代码段数据段启动分析
    第45讲ARM处理器接口编程-按键编程实现(上)
    第46讲ARM处理器接口编程-按键编程实现(下)
    第47讲ARM处理器接口编程-中断系统分析(上)
    第48讲ARM处理器接口编程-中断系统分析(下)
    第49讲ARM处理器接口编程-外部中断编程实现(上)
    第50讲ARM处理器接口编程-外部中断编程实现(下)
    第51讲ARM处理器接口编程-PWM定时器编程实现(上)
    第52讲ARM处理器接口编程-PWM定时器编程实现(下)
    第53讲ARM处理器接口编程-看门狗定时器编程实现(上)
    第54讲ARM处理器接口编程-看门狗定时器编程实现(下)
    第55讲ARM处理器接口编程-实时时钟原理分析
    第56讲ARM处理器接口编程-基于ARM的万年历编程实现(上)
    第57讲ARM处理器接口编程-基于ARM的万年历编程实现(下)
    第58讲ARM处理器接口编程-嵌入式通信方式原理分析
    第59讲ARM处理器接口编程-UART串口编程实现(上)
    第60讲ARM处理器接口编程-UART串口编程实现(下)
    第61讲ARM处理器接口编程-AD转换编程实现(上)
    第62讲ARM处理器接口编程-AD转换编程实现(下)
    第63讲ARM处理器接口编程-触摸屏编程实现(上)
    第64讲ARM处理器接口编程-触摸屏编程实现(下)
    第65讲ARM处理器接口编程-LCD显示器原理分析(上)
    第66讲ARM处理器接口编程-LCD显示器原理分析(下)
    第67讲ARM处理器接口编程-LCD显示器编程实现(上)
    第68讲ARM处理器接口编程-LCD显示器编程实现(下)
    第69讲ARM处理器接口编程-NandFlash编程实现(上)
    第70讲ARM处理器接口编程-NandFlash编程实现(下)

    下载地址:
    链接: http://pan.baidu.com/s/1jGyu4y6 密码: 2iey[/size]
    展开全文
  • 嵌入式Linux驱动程序设计从入门到精通:ffe0844001a2f011b.zip
  • 德国倍福BECKHOFF嵌入式PC从入门到精通V26(2).pdf,兼容C++、C# ,可在Visual Studio开发环境下编程
  • ARM嵌入式Linux系统开发从入门到精通,里面有详细的讲解,很适合初学着看!
  • 第一部分 1, Altium 历史,以及产品介绍,2, DXP 系统平台介绍,3, Altium Designer 设计环境,4, Altium 免费资源,支持及帮助中心,5, PROTEL Altium Designer,6, 原理图编辑基础,7, 原理图绘图工具...
  • 《JavaScript从入门到精通》附带的ppt 《JavaScript从入门到精通初学者角度出发,通过通俗易懂的语言、丰富多彩的实例,详细介绍了使用JavaScript语言进行程序开发应该掌握的各方面技术。全书共分24章,包括初识...
  • 嵌入式linux入门到精通,非常不错的资源。
  • ARM嵌入式Linux系统开发从入门到精通,里面有详细的讲解,适合初学着看!. 这个中间 有书的pdf文档 还有源码
  • 课程按篇章可分为5篇,单独的视频专栏观看: 【第1篇】(IMX6ULL)新学习路线、视频介绍、资料下载、开发板基础操作 【第1...开发板使用手册 【第4篇】嵌入式Linux应用开发基础知识 【第5篇】嵌入式Linux驱动开发基础知识

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 8,285
精华内容 3,314
关键字:

嵌入式从入门到精通