ARM笔记

来源:互联网 发布:ug多轴编程视频 编辑:程序博客网 时间:2024/05/01 11:56
一.ubuntu系统需要安装的软件包

二.课程SDK
Linux 嵌入式Linux系统相关
    images  嵌入式Linux系统镜像(rom)
    prebuilts 交叉编译工具链
    src 嵌入式Linux系统源码
    tools 开发工具

package 软件包
    sudo apt-get install stardic
    sudo cp dic/* /usr/share/stardict/dic/ -rf

extern 软件包

三.嵌入式系统
    不带系统
         MCU
    带系统    
        SOC  Linux/Android     

四.工作岗位
    硬件工程师(设计电路画板)
    软件工程师
        应用程序开发
        驱动开发

    第一次开发:半导体原厂做,高通 三星 飞思卡尔 TI 小米 华为 联发科 全志
    第二次开发:开发板解决方案厂商
    第三次开发:项目
    
五.ARM
    arm

    cpu           SOC
    经典处理器:
    arm7 ------> S3C44B0
    arm9 ------> S3C2410/S3C2440
    arm11 -----> S3C6410
    cortex系列:
    arm-cortex-a
        a8     S5PV210  三星 单核 win android linux
            AM335    TI  单核 win android linux
        a9    Exynos4412    三星 4核
            Omap4460 TI 双核
            S5P4418 三星 四核
            Imax6Q  NXP 四核
            Imax6D    NXP 双核
        a15     Exynos5210 三星 8核心(4个a15,4个a7)
    arm-cortex-m
        m3    stm32f103
        m4    stm32f407
        m7    stm32f707
    arm-cortex-r
        realtime
    V8:arm-cortex-a
        a50
            a53    S5P6818
            a57
        a72
        a73    

S5P6818开发板启动方式
    1.sd启动
    2.emmc    
    3.usb
    
六.软件架构
应用程序
/ init进程---->其他进程
kernel    进程管理 内存管理 文件系统支持 网络 设备驱动,挂载根文件系统
bootloader 初始化硬件,加载内核
原厂启动代码 初始化基本硬件,检测启动方式,加载bootloader
-----------------------------------------------------
SOC+DDR(1G)+EMMC(8G)+LCD+SOUND+NET+WIFI+BLE+USB+.........

七.Andriod系统和Linux系统
    Android手机
    emmc{bootloader uImage ramdisk [system][data][cache][storage]}
    bootloader---->uImage---->ramdisk(内存)
                /system 系统软件
                /data    用户自己安装的软件\通讯录\配置
                /cache    
                /storage 用户软件产生的数据
    Android系统的rom:
        bootloader
        uImage
        ramdisk
        system.img    
        userdata.img
        cache.img

    针对我们的开发板:
    emmc{bootloader [uImage ramdisk][system][data][cache][storage]}
    Android系统的rom:
        bootloader
        boot.img
        system.img    
        userdata.img
        cache.img
    

    Linux系统:
    emmc{booloader uImage [rootfs]}    
    Linux系统的rom:
        bootloader
        uImage
        rootfs.img    
    针对我们的开发板:
    emmc{booloader [uImage][rootfs]}    
    Linux系统的rom:
        bootloader
        boot.img
        rootfs.img
=========================================================================================
八.刷机原理
    1.板子首次启动需要sd卡启动
    2.sd中的bootloader启动后运行fastboot命令进入刷机模式
    3.pc把刷机rom发送给开发板,开发板的fastboot把收到的镜像文件写到emmc的合适位置

九.刷机    
    刷机Linux系统:
    Linux系统rom:/home/zyli/6818/s5p6818sdk_lzy1/Linux/images    
    S5P6818如果从sd卡启动,会从sd卡的第二个扇区读取bootloader
    sd{512bytes|bootloader [--------------------][-----------------]}    
      /dev/sdx             /dev/sdx1         /dev/sdx2

    1>建立sd分区
        参考<建立sd卡分区.mp4>
    2>把bootloader烧写到sd卡
        sudo dd if=./ubootpak.bin of=/dev/sdx seek=1
    3>配置minicom
        安装:sudo apt-get install minicom
        配置:sudo minicom -s
                   +-----[configuration]------+
                       | Filenames and paths      |
                       | File transfer protocols  |
                       | Serial port setup        |
                       | Modem and dialing        |
                       | Screen and keyboard      |
                       | Save setup as dfl        |
                       | Save setup as..          |
                       | Exit                     |
                       | Exit from Minicom        |
                       +--------------------------+
               选择Serial port setup
                +------------------------------------------+
                    | A -    Serial Device      : /dev/ttyUSB0 |
                    | B - Lockfile Location     : /var/lock    |
                    | C -   Callin Program      :              |
                    | D -  Callout Program      :              |
                    | E -    Bps/Par/Bits       : 115200 8N1   |
                    | F - Hardware Flow Control : No           |
                    | G - Software Flow Control : No           |
                    |                                          |
                    |    Change which setting?                 |
                    +------------------------------------------+
        运行:sudo minicom

    4>在开发板上运行uboot,在minicom中观察启动过程
        a>运行minicom
        b>把sd卡插入卡槽(前提是在sd卡中烧写了bootloader)
        c>给开发板上电(或者重启),在minicom中观察启动过程
        d>在启动后,minicom中会有倒计时,在倒计时完成前敲键盘的任意键
        e>敲任意键后板子会进入uboot提供的shell命令行
            [zyli@Uboot]#
        
    5>fastboot刷机
        确保:usb线以及连接
        a>在uboot的shell中执行fastboot
            [zyli@Uboot]# fastboot
        b>在电脑上执行刷机命令
            [ubuntu@Ubuntu]# sudo fastboot devices
            [ubuntu@Ubuntu]# sudo fastboot flash ubootpak ./ubootpak.bin
            [ubuntu@Ubuntu]# sudo fastboot flash boot ./boot.img
            [ubuntu@Ubuntu]# sudo fastboot flash system ./rootfs.ext2
        c>切换到minicom
            在minicom中执行Ctrl+C
            [zyli@Uboot]#
    6>修改环境变量
        目的:告诉告诉开发板内核和根的位置
        注意:以下命令在开发板上(也就是minicom中)执行
        bootloader启动后3s如果没有敲键盘则bootloder会默认执行环境变量bootcmd指定的操作
        [zyli@Uboot]# set bootcmd "ext4load mmc 2:1 0x48000000 uImage;bootm 0x48000000"
        解释:ext4load 命令  从emmc中把文件加载到内存
             uImage 被加载的文件
             mmc 固定
             2:1  2代表第二个设备 板子上有三个mmc设备(sd0, sd1, emmc)
             0x48000000 开发板的内存地址
            
             bootm 命令 启动内核

        注意:接下来要告诉内核根的位置
        [zyli@Uboot]# set bootargs root=/dev/mmcblk0p2 tp=gslx680-linux
        注意:如果是mipi接口的屏幕,需要增加一个参数lcd=wy070ml
        解释:bootargs这个环境变量的值最终会传给内核
             root 指定根的位置
             /dev/mmcblk0p2
            内核启动后会识别emmc,emmc被识别为/dev/mmcblk0     
            两个分区分别被识别为/dev/mmcblk0p1 /dev/mmcblk0p2            
             tp执行触摸屏的类型

        注意:环境变量修改后需要保存
        [zyli@Uboot]# save
    7>重启开发板
        如果正常的话会进入linux系统
        在开发板的屏幕上会出现基于QT5的界面
        在minicom中会出现要求登录的界面(用户名root,密码123456)

    
    刷Android系统:
    1>在开发板运行fastboot命令
        [zyli@Uboot]# fastboot
    2>在PC上依次执行如下命令
         [ubuntu@Ubuntu]# sudo fastboot flash ubootpak ubootpak.bin
         [ubuntu@Ubuntu]# sudo fastboot flash boot boot.img
         [ubuntu@Ubuntu]# sudo fastboot flash system system.img
         [ubuntu@Ubuntu]# sudo fastboot flash userdata userdata.img
         [ubuntu@Ubuntu]# sudo fastboot flash  cache cache.img
    3>修改环境变量
        [zyli@Uboot]# set bootcmd "ext4load mmc 2:1 0x48000000 uImage;ext4load mmc 2:1 0x49000000 root.img.gz;bootm 0x48000000"
        [zyli@Uboot]# set bootargs lcd=vs070cxn tp=gslx680
        [zyli@Uboot]# save
        [zyli@Uboot]# reset
    
    给Android安装软件
        adb 可以通过usb控制android系统
        安装adb:
        [ubuntu@Ubuntu]# sudo apt install android-tools-adb    
        利用adb给Android系统安装软件:
        [ubuntu@Ubuntu]# adb devices
        [ubuntu@Ubuntu]# adb install 100Project.apk
        
=========================================================================================
十.编译Linux系统rom
    uboot
        解压uboot源码:
        [src]$ tar -xvf uboot6818.tar.bz2
        [src]$ cd uboot
        [uboot]$ make x6818_config
        [uboot]$ vim include/configs/x6818.h
            141 #define CONFIG_SYS_PROMPT   "[uplooking@Uboot]# "

        交叉编译工具链:
            arm-eabi-gcc    
            arm-eabi-ld
            arm-eabi-as
            arm-eabi-objdump
            arm-eabi-objcopy
            arm-eabi-nm
        配置交叉编译工具链:
        [uboot]$ vim Makefile     
         203 CROSS_COMPILE=/home/zyli/6818/s5p6818sdk_lzy1/Linux/prebuilts/gcc/linux-x86/arm/arm-eabi-4.8/bin/arm-eabi-
        [uboot]$ vim board/s5p6818/x6818/config.mk
         27 CROSS_COMPILE=/home/zyli/6818/s5p6818sdk_lzy1/Linux/prebuilts/gcc/linux-x86/arm/arm-eabi-4.8/bin/arm-eabi-

        编译:
        [uboot]$ make -j4
        [uboot]$ sudo cp tools/mkimage /usr/bin

        ####
        u-boot-->u-boot.bin-->ubootpak.bin
        ####
        
    kernel
        [src]$ tar -xvf linux-3.4.tar.bz2
        [src]$ cd kernel/
        [kernel]$ make x6818_defconfig    
        [kernel]$ vim Makefile
            195 ARCH            ?= arm
             196 CROSS_COMPILE   ?= /home/zyli/6818/s5p6818sdk_lzy1/Linux/prebuilts/gcc/linux-x86/arm/arm-eabi-4.8/bin/arm-eabi-
        [kernel]$ make -j4

        #####
        vmlinux--->arch/arm/boot/zImage----uImage
        uboot要求在zImage前面加一个头[arm Linux]zImage
        #####

        ##制作uImage:
        [kernel]$ make uImage
        
        ##制作boot.img:
        [tools]$ tar -xvf boot.tar.bz2
        [tools]$ cd boot
        ##删掉和Linux系统无关的文件
        [boot]$ rm debug-ramdisk.img ramdisk-recovery.img root.img.gz
        ##用我们自己的内核替换原来的内核
        [boot]$ cp ../../src/kernel/arch/arm/boot/uImage ./
        [boot]$ cd ..
        ##制作镜像文件
        [tools]$ ./make_ext4fs -s -l 64M -L linux boot.img boot

    rootfs
        #####
        根文件系统:硬盘一个分区   /
        abc    dev         initrd.img.old  libx32      nfsroot  run   
        bin    etc         lib             lost+found  opt      sbin  
        boot   home        lib32           media       proc     snap  
        cdrom  initrd.img  lib64           mnt         root     srv   
        
        Busybox:工具集---->命令
        
        buildroot:busybox qt5 python go mplayer mpg123
        #####
        [src]$ tar -xvf buildroot.tar.bz2
        [src]$ cd buildroot/
        [buildroot]$ make x6818_defconfig
        [buildroot]$ make -j4
        [buildroot]$ vim output/build/host-ncurses-5.9/include/curses.tail
            104 extern NCURSES_EXPORT(bool)    mouse_trafo (int*, int*, bool);
        [buildroot]$ make -j4

        编译完成后:buildroot/output/images/rootfs.ext2


        经过编译:ubootpak.bin boot.img rootfs.ext2

刷机:正真产品发布的时候

开发:uboot---->sd
     uImage---->tftp
     rootfs---->nfs

=========================================================================================
十一.tftp
    作用:用于开发板从PC下载文件,直接把文件下载到内存

    配置tftp服务器:
        配置方法参考<www.embsky.com><ubunut下配置tftp服务器>

    开发板的uboot中自带tftp客户端:
        确保:开发板和PC之间要联网
        [lzy@Uboot]# set ipaddr 192.168.100.250    
        [lzy@Uboot]# set serverip 192.168.100.199
        [lzy@Uboot]# save
        [lzy@Uboot]# ping 192.168.100.199
            如果提示not alive则再次ping
        
        [lzy@Uboot]# tftp 0x48000000 uImage
        ###下载成功的界面:
        Speed: 1000, full duplex
        Using dwmac.c0060000 device
        TFTP from server 192.168.100.199; our IP address is 192.168.100.250
        Filename 'uImage'.
        Load address: 0x48000000
        Loading: #################################################################
                 #################################################################
                 #################################################################
                 #################################################################
                 #################################################################
                 ##########################################
                 2.6 MiB/s
        done
        Bytes transferred = 5383216 (522430 hex)
    
        ##测试文件的正确性
        [lzy@Uboot]# bootm 0x48000000    
    
笔记本与开发板网络链接方法:
    开发板与PC的以太网卡直连
    PC的wifi与路由器链接用来上外网
    <详细内容参考 网络配置.mp4>

十二.网络文件系统
    1>在PC上配置nfs服务
    [redis]$ sudo apt-get install nfs-kernel-server
    [redis]$ sudo vim /etc/exports
        /redis_root *(rw,sync,no_root_squash)
    [redis]$ sudo mkdir /redis_root
    [redis]$ sudo chmod 777 /redis_root/
    [redis]$ sudo /etc/init.d/nfs-kernel-server restart
    
    2>测试
    [buntu@Ubuntu]# sudo mount 192.168.200.172:/redis_root /mnt
        然后可以通过访问/mnt来达到访问对方redis_root的目的
    [buntu@Ubuntu]# sudo unmount /mnt

十三.搭建nfs网络根文件系统
    [images]$ sudo tar -xvf rootfs.tar -C /redis_root/
    
十四.让开发板内核启动后挂在nfs
    [lzy@Uboot]# set bootargs root=/dev/nfs nfsroot=$serverip:/redis_root ip=$ipaddr tp=gslx680-linux
    [lzy@Uboot]# save

十五.启动开发板
    为了避嫌我们先把emmc擦除掉
    [lzy@Uboot]# mmc erase 0 10240
    [lzy@Uboot]# ping $serverip
    [lzy@Uboot]# tftp 0x48000000 uImage
    [lzy@Uboot]# bootm 0x48000000

问题:
    当Linux挂在nfs后,启动init进程---->执行脚本(/etc/init.d/rcS)---->执行其他脚本
=========================================================================================

十六.嵌入式应用软件开发
    扩展buildroot
    <参考视频 BuildRoot扩展选项.mp4>

    安装交叉编译器:
    [extern]$ tar -xvf arm-linux-gcc-4.5.1.tar.bz2
    [extern]$ vim ~/.bashrc
        PATH=/home/zyli/6818/s5p6818sdk_lzy1/extern/4.5.1/bin:$PATH
    [extern]$ source ~/.bashrc
        

    本地程序开发:
        在PC上对程序进行交叉编译:
        [ubuntu@Ubuntu]# touch hello.c
            #include <stdio.h>
            int main(void) {printf("hello arm\n");}    
        [ubuntu@Uboot]# arm-linux-gcc hello.c -o hello
        把程序拷贝到共享目录
        [ubuntu@Uboot]# cp hello /redis_root

        在开发板上启动内核,并且挂载nfs
        [x6818@localhost]# /hello
            hello arm
    

    QT程序开发:
        1>创建QT工程,编写代码,在PC测试运行
        2>交叉编译
            [test]$ cp qtemb/ qtemb_board -rf
            [test]$ cd qtemb_board
            [qtemb_board]$ ~/6818/s5p6818sdk_lzy1/Linux/src/buildroot/output/host/usr/bin/qmake
            [qtemb_board]$ make
        3>把程序放到开发板执行

    让自己开发的程序能够自启动
        1>改变开发板根文件系统中的文件
            [ubuntu@Ubuntu]$ sudo vim /redis_root/etc/init.d/S99qttest
            或者:
            [x6818@localhost]# vim /etc/init.d/S99qttest
            修改如下:
                    #/usr/share/demo/qttest &
                    /usr/bin/qtemb &
        2>让开发板能够自动下载内核和启动内核
            [lzy@Uboot]# set bootcmd "ping 1;ping 2;tftp;tftp;bootm"
            [lzy@Uboot]# save
======================================================================================

十七.远程登录开发板
    [ubuntu@Ubuntu]# ssh root@192.168.200.123

十八.嵌入式软件移植例子
    移植sqlite3
    [下载]$ tar -xvf sqlite-autoconf-3200100.tar.gz
    [下载]$ cd sqlite-autoconf-3200100/
    [sqlite-autoconf-3200100]$ mkdir /redis_root/sqlite
    [sqlite-autoconf-3200100]$ ./configure --prefix=/redis_root/sqlite/ --host=arm-linux CC=arm-linux-gcc --enable-shared --enable-static
    [sqlite-autoconf-3200100]$ make -j4
    [sqlite-autoconf-3200100]$ make install
=====================================================================================

作业前传:
    1>数据库基本使用
    2>嵌入式QT中调用数据库

作业:
    计算器改造:
    1>把计算历史存储到数据库   1 + 2 + 3 = 6
    2>在计算器界面增加两个按键,用来查看计算历史
=====================================================================================

问题解决:
    home分区太小 根大
    sudo mkdir /document
    sudo chown zyli:zyli /document
    ln -s /document ~/document    
=====================================================================================

十九.Arm架构和Arm汇编
    -5    1000000000.....101
          1111111111.....011 >> 1
              1111111111.....101---->10000000.....011
              0111111111.....101---->2^31-1-2
                                                           |-----与外界通信  
    ARM=Arm_Core+MMU+协处理器+Cache+Cache控制器+TCM+总线接口+移位器+........
        |     |    |       |----I-cache     |---I-TCM     |---<< >>
        |     |    |       |----D-cache        |---D-TCM
        |     |    |------控制CP15
        |     |    |------调试CP14
        |     |----内存管理单元(虚拟到物理的转换)
        |---------执行指令,r0,r1,...,r15
    
    Arm处理器的模式
        七种模式:
        -普通模式 user 用来执行进程代码
        -特权模式 system
          -异常模式
            irq 用来执行中断代码
                --产生了中断
            fiq 用来执行快速中断代码
                --产生了快速中断
            und 用来处理未定义指令
                --1.cpu遇到了未定义指令
            svc 用来执行bootloader和内核
                 -----swi/svc用来由user切换到svc(arm平台的系统调用)
                 -----reset(上电,重启按钮,看门狗)
            abt 用来处理中止异常
                --1.越界
                --2.内存地址不存在
        cpu上电运行的默认模式:
            svc
                    
        新增的模式:
            1.虚拟化模式
            2.安全    
        
    指令集
        Arm指令     32位/高效
            经典处理器 a系列
        Thumb指令   16位
            早期的经典处理器
        Thumb2指令  32/16位    
            m系列

    流水线
        arm7
        取指 译码 执行
        6----------------
        5----------------
        4----------------
        3----------------取指  
        2----------------取指 译码
        1----------------取指 译码 执行
    
    寄存器
        参考<arm架构手册.pdf> P43
        R0, R1, R2 .... R15
        每一种异常模式都有自己的R13/R14

        R0-R12 32位

        R13  SP stack pointer
        R14  LR link register
        
        R15 PC 指向正在被取指的指令

        R9  SB
    
        bar:
        -------push {lr}-----
        ---------------------
        ---------------------
        ---------------------
        ---------------------
        -------pop {lr}------
        --------bx lr-------- PC=LR
        foo:
        -------push {lr}-----
        ---------------------
        ---------------------
        -----bar()-bl bar---- LR=下一条指令的地址 PC=bar
        ---------------------
        -------pop {lr}------
        --------bx lr-------- PC=LR
        main:
        -------push {lr}-----
        ---------------------
        ----foo()-bl foo----- LR=下一条指令的地址 PC=foo
        ---------------------
        -------pop {lr}------
        --------bx lr--------

    结构
        哈佛结构
            指令和数据分开存放

        arm7
        冯诺依曼结构
            指令和数据一起存放

        arm7---cahce----ddr

        arm---I-cache
            --------cache------ddr
               ---D-cache    

        6----------------
        5----------------
        4----------------
        3----------------取指  
        2----------------取指 译码
        1----------------取指 译码 执行  把一个数据存放到内存 *p=123

        arm-cortex-a8 只能做单核
        arm-cortex-a9/15/53 多核
        
        a8自带一级和二级cache
        arm---I-cache
            --------cache-
               ---D-cache    

        a9只有一级cache
        arm---I-cache
               ---D-cache    
        
    ARM汇编
        Arm常用指令参考<Arm常用指令集.pdf>
        代码参考<code/base/>

        汇编指令<--汇编-->机器码
        hello.c--->hello.s---->hello.o--->hello
    
        内嵌汇编  在C/C++中写汇编

        语法:
        1.
        unsigned int register c asm("sp");
        unsigned int register c asm("r0");
        c = 0x100;

        2.
        int main() {
            int a = 5;
            int b = 6;
            int c;
            
            //C

            asm volatile(

            );
            __asm__ __volatile__(
                "mov r0, #20\n"
                "mov r0, #20\n"
                "mov r0, %[aa]\n"
                "mov r0, %1\n"
                "mov %0, #2\n"
                "r0,"
                "#20\n"
                :[bb]"=&r"(b), [cc]"+r"(c)声明输出变量和输入输出变量
                :[aa]"r"(a)声明输入变量
                :"r0"保护寄存器和内存
                注意:&表示输出不采用输入变量使用过的寄存器
            );
        }
        
    =======================================================================
    插曲:通过网络把文件从PC拷贝到board
    前提:板子已经启动(根在emmc)
    保证:板子和PC之间能够ping通

    在板子上执行如下命令:
    [root@X6818:~]# mount -t nfs -o nolock,rw 172.16.170.179:/redis_root /mnt
    =======================================================================
    通过串口下载文件
    保证:minciom正常启动
             开发板启动Linux系统
         进入[root@X6818:~]#
    
    操作:
        ctrl+a--->z--->s
    =======================================================================

    
    反汇编 arm-linux-objdump -D 04in_out >04in_out.s

    8388:       e3a0000f        mov     r0, #15
        838c:       e3a00eff        mov     r0, #0x00000ff0       ; 0xff
                    mov     r0, #0x7f8
                        0111 1111 1000--->ff  3
                        e3a00eff
                    mov     r0, #0x3f4
                        0011 1111 0100--->fd  2
                           e3a00ffd
    0xe = 14 * 2 = 28
    32 - 28 = 4
    
    立即数规则:1.本身小于等于255
           2.经过循环右移偶数位之后小于等于255
           3.特殊情况 mov r0, #0xffffff00
                  mvn r0, #0xff

    CPSR 当前程序状态寄存器        
        31  30  29
        N   Z   C   V   Q    EAIFT        M[4:0]
        E:如果E==1代表大端,否则为小端(默认),任何模式不得改变
          但是通过协处理器cp15可以修改
        A:中止禁止位,如果为1代表禁止
        I:中断禁止位
        F:快速中断禁止位
        T:thumb
        user模式只能修改NZCVQ
        M:表示当前处理器的模式,特权模式下可以修改
        N:如果出现了负操作,那么N会被硬件置1,否则清零
        Z:如果出现了0操作,那么Z会被硬件置1,否则清零
        C:加法,如果进位了会被硬件置1,否则清零
                  减法,如果借位了会被硬件清零,否则置1
    注意:如果指令的结果想影响cpsr的标志为,那么指令需要+s

    0x60030010
    0110 0000 0000 0011 0000 0000 0001 0000

    伪指令:cpu不承认 但编译器承认
    ldr r0, =0x12345678   ------> r0=0x12345678

    make环境变量
    [base]$ export CC=arm-linux-gcc
    [base]$ export CFLAGS=-march=armv7-a
    [base]$ make 07mul
    arm-linux-gcc -march=armv7-a    07mul.c   -o 07mul

    条件执行
    a = 5; b = 6;
    if (a > b) {         a - b ---> NZ N=1 Z=0
        c = 1;        N=0 && Z=0
        xxxx
    } else {
        c = 0;        N=1 || Z=1
        yyyyy
    }

    arm指令大部分可以加条件 lt gt le ge ne eq
        moveq r0, #123   Z=1
    
    跳转

    while(1); for(;;);----------------------> b .

    PC 是一寄存器,保存永远都是正在被取指的指令,也就是正在被执行指令的下下条指令的地址
    bl biaohao 在跳转到标号所指定的代码段执行之前会把bl的下一条指令的地址保存到lr

    APCS规则:规定了C/C++和汇编之间相互调用的规则
        1.编译器
        2.程序员

        1.传参 r0-r3 多余的参数从后往前依次入栈
        2.栈 满递减栈
            fd
            fa
            ed
            ea
        3.返回值 r0  r1r0
            

总结:
    一.嵌入式系统架构
    二.刷机
    三.编译
    四.tftp nfs
    五.作业
    六.Arm架构
    七.汇编语言    

二十.裸板开发
    模板
    ├── inc
    │   ├── common.h
    │   └── hw.h
    ├── Makefile
    └── src
        ├── hw.c
        ├── main.c
        ├── Makefile
        └── start.s
    裸板代码编译:
    [src]$ arm-linux-gcc -c -o hw.o hw.c -I../inc
    [src]$ arm-linux-gcc -c -o main.o main.c -I../inc
    [src]$ arm-linux-as -o start.o start.s
    [src]$ arm-linux-ld start.o main.o hw.o -o arm -Ttext 0x50000000
    [src]$ arm-linux-objcopy -O binary arm arm.bin

    链接地址:假设的程序运行地址
    位置相关:运行地址必须==链接地址    
    位置无关:运行地址可以!=链接地址

    注意:为了保证程序能够正常执行,最好运行地址==链接地址
    
    在Uboot源码中可以找到System.map,在这个文件中可以找到printf的地址
    0x43c1c5e0    

    GPIO
        通用的输入输出口
        可以配置输出功能或者输入功能或者其他功能
    
    SOC S5P6818简介
        SMP/AMP

        SOC ---> SCP 需要外接内存
              POP 自带内存    
        3个mmc接口
            0--->msd
            1--->msd
            2--->emmc
                emmc/nand
                 emmc=控制器+nand
                    
    UART/USART
    115200 8N1     
    9600
    38400

    发送寄存器  FIFO    发送器-------------------------->>>>------------------
    接收寄存器  FIFO     接收器--------------------------<<<<------------------

    数据传输方式:
    1.DMA
    2.irq GIC VIC NVIC
    3.poll    

##################################################################################
内核驱动: 内核接口  硬件

c /dev/ttyUSB0    /dev/my-led
--------------------    
uart_driver:1.内核
        2.硬件
led_drivrer:1.内核
        2.硬件
-------------------
uart硬件 led buzzer wdt
                
##################################################################################
项目使用:使用QT操作uart
<参考嵌入式天空:QT5.8编程之串口编程>