嵌入式学习一阶段——交叉开发

二、交叉开发的概念

是指在通用PC端把程序编写、编译好之后,再下载到嵌入式产品中去运行
​
为什么要用交叉开发?
​
(1)大多数的嵌入式产品只有运行环境。没有编译环境
​
(2)程序员的工作环境更加舒适、安全

三、GEC-6818开发板简介

四、网络设置

1)设置虚拟机IP
​
1>虚拟机设置--》网络适配器--》桥连模式--》勾选上复制物理网络连接状态
​
2>设置--》网络--》设置--》IPV4-->改为手动分配IP--》设置IP地址、子网掩码、网关
​
--->重新打开网络连接
​
输入指令查看:
​
ifconfig
2)设置开发板IP
​
打开开发板的启动配置文件
​
vi   /etc/init.d/rcS

在文件的最末尾添加:

ifconfig eth0 down
​
ifconfig eth0 hw ether 08:09:00:A0:38:68
​
ifconfig eth0 172.8.0(1).xx netmask 255.255.254.0 up
重启开发板即可

五、开发板的使用

1)先用串口线把开发板与电脑相连接
​
2)打开开发板控制终端(下载SecureCRT)
​
3)打开电脑的设备管理器,查看是否识别到了端口(快捷键:windoes+x)
​
如果没有识别出来端口--》请安装驱动
​
4)SecureCRT连接设置
​
协议:serial协议: 串口协议
​
端口:你设备管理器中识别出来的端口
​
波特率:115200
​
去掉流控RTS/CTS的勾选 ====》连接

开发板上电之后,会有一个自启动程序,该程序会占用终端,

按下CTRL + C把开发板自启动程序杀掉

六、文件下载

1)串口下载

(1)使用 rx 命令下载
​
使用语法:
​
rx 需要下载的文件名
​
点击传输--》发送xmodem
​
(2) 使用 rz 命令下载
​
1、安装 rz工具
​
2、解压
​
    tar -vxf arm-rz.tar.xz
​
3、运行 arm-rz文件中的rzconf.sh
​
4、使用rz下载文件
​
语法:
    rz 回车

2)通过 tftp 网络协议下载文件 tftp 和 ftp 都是用来传输文件的一种网络协议 tftp 实现是采用UDP协议 ftp 实现是采用 TCP 协议

tftp 只能用来传输文件(不能传输其他东西)
    使用步骤:
        1>先在虚拟机上安装 tftpd-hpa 工具
            sudo apt-get install tftpd-hpa
​
        2>配置 tftpd-hpa:
            sudo vim /etc/default/tftpd-hpa
​
        3>(第一次安装)需添加内容:
            TFTP_USERNAME="tftp"  //创建一个tftp的共享文件目录
            TFTP_DIRECTORY="/home/china/tftpboot" //创建一个tftpboot共享文件目录
            TFTP_ADDRESS="0.0.0.0:69"
            TFTP_OPTIONS="-l -c -s"
​
        4> 设置 tftp共享目录的权限
            chmod 0777 /home/china/tftpboot
​
            第一次使用tftp时,需要手动启动tftp服务:
                sudo service tftpd-hpa start
​
            后续使用就不需要在启动,可以使用重启:
                sudo service tftpd-hpa restart
​
            停止tftp服务:
                sudo service tftpd-hpa stop
​
    开发板从指定的 tftp 服务器 下载文件 或 传输文件
      开发板下载命令:   tftp -g -r 要下载的文件名 172.8.0.xxx (虚拟机的IP)
      开发板传输文件命令: tftp -p -r 要传输的文件名 172.8.0.xxx(虚拟机IP)
            注意:要下载的文件 必须要在tftpboot共享文件目录下
                要传输前,请先确保你的 tftpboot中存在这个文件

七、交叉编译 (1)采用交叉编译的规则去编译文件 arm-linux-gcc 1.c -o 1 arm-linux-gcc 是交叉编译工具

(2)把生成的可执行文件下载到开发板
    rx 1
​
(3)给可执行文件增加可执行权限
    chmod +x 1
​
(4)运行程序
    ./1

八、GCC编译过程 gcc hello.c -o hello

编译过程是不是一步到位的?    //不是
编译过程:
    (1)预处理
            处理代码中所有以'#'开头的行  主要处理:头文件以及宏定义
            语句:
                gcc -E hello.c -o hello.i //hello.i还是一个c文件
​
    (2)编译
            把C文件编译成汇编文件(有语法的转换),会进行语法分析,有错误会报错
            语句:
                gcc -S hello.c -o hello.s //hello.s 就是一个汇编文件
​
    (3)汇编
            把汇编文件生成一个可执行文件(机器指令)--》二进制文件
            语句:
                gcc -c hello.s -o hello.o //hello.o 就是一个二进制文件
​
    (4)链接
            把所有的.o文件链接起来,生成一个目标文件
            语句:
                gcc 1.o 2.o main.o -o main
​
为什么编译过程不能一步到位?  //效率考虑

库(library) 是一种代码的封装形式,简单的说,库中封装着一堆目标文件(.o)

当封装好了一个库之后,在其他地方就可以直接调用,但是用户却看不到具体的实现,不会造成源代码的泄漏。

根据库的不同的封装和链接形式,分为动态库、静态库

1、动态库

操作流程:

1)创建(封装)一个动态库

(1)编写源代码
​
1.c 1.h   2.c 2.h main.c(主程序)
​
(2)把源代码先编译成目标文件
​
gcc -c -fpic  1.c -o 1.o
​
gcc -c -fpic  2.c -o 2.o
​
(3)把目标文件封装成一个库
​
gcc -shared 1.o 2.o -o libxxx.so  / gcc -shared  -o libxxx.so  1.o 2.o
​
注:
​
-fpic  :  表示要生成的库与位置无关(简单的理解:库中的函数不知道会被哪个程序调用)
​
---(再简单的说,就是生成一个任意程序都能调用的动态库)
​
-o  : 表示指定生成目标文件
​
-shared: 表示要编译一个动态库(共享库)
​
libxxx.so : lib是库的前缀,.so是动态库的后缀,xxx是动态库

其实也可以把以上两步合为一:

gcc -shared  -fpic -o libxxx.so 1.c 2.c (跟编译器环境有关)

2)链接一个动态库 要想使用一个动态库的话,一般来讲需要提供对应的 .h 文件以及 .so 文件 然后用户编译的时候,只需要指定头文件与库文件的路径 以及 库的名字,就可以使用库

格式如下:
        gcc  main.c  -I头文件路径 -L库路径 -l库名 -o main

3)直接运行程序会报错,因为动态库的使用必须要修改动态库搜索路径 1>把你的动态库加入到系统默认的动态库搜索路径下 cp libxxx.so /usr/lib

2>手动添加动态库搜索路径
    在终端输入:
        export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/mnt/hgfs/CS2322/19.交叉开发/code

2、静态库 使用动态库时,链接时需要添加动态库的路径,运行程序时也需要指定动态库的搜索路径 程序与动态库相互独立,彼此依赖

静态库的做法,与动态库不太一样,静态库在使用时是不需要添加库搜索路径,因为静态库在链接这一步骤时,
就已经把静态库的内容拷贝到程序中。
    即程序本身运行过程中不再需要依赖静态库

操作流程: 1)编写源文件 1.c 1.h main.c(主程序)

2)编译源文件得到目标文件
    gcc -c   1.c -o 1.o
​
3)封装库
    ar -rc libxxx.a 1.o
​
注:
        ar : 封装一个静态库
        -rc: -r代表插入目标文件到静态库中,-c代表创建指定的静态库
        libxxx.a : lib是库的前缀,xxx是库名,.a是静态库的后缀
​
4)链接静态库
    用户编译程序时,只需要指定头文件、库文件路径,以及库文件名就可以使用,形式如下:
        gcc main.c -o main -I头文件路径 -L库路径 -l库名
​
5)直接运行程序即可,不需要考虑环境变量

3、动态库与静态库的异同 1)动态库与静态库都是目标文件(二进制文件)的封装 2)对于动态库: 在编译程序时,并没有把动态库的内容添加进程序中,就仅仅是做了一个标记,表示需要 使用动态库的内容,当执行程序时,还需要指定动态库的搜索路径,才可以正常使用动态库 对于静态库 : 编译程序时,会直接把静态库的内容拷贝到程序中去,运行程序,就不再需要静态库

3)我们一般来讲,使用动态库比较多
    理由:
        1> 程序运行时,动态库只需要存在一份,但是静态库可能会存在多次拷贝,会造成代码的冗余
        2> 当库进行更新时,对于动态库来讲,在接口不变的情况下,则不需要重新编译程序
            对于静态库来说,库一旦发生改变,所有使用了该库的程序都需要重新编译

Makefile

Makefile 目标:完成一个简单的makefile文件即可 makefile(工程管理文件) 是一个脚本,用来实现自动化编译工程文件。

当我们执行make命令时,会自动找到相应的makefile文件
    然后根据其makefile制定的规则去生成文件
​
make有两种用法:
    make  -->make后面不带参数,那么默认执行第一条命令
    make cmd -->指定执行cmd命令
​
要使用make命令,需要先下载make工具包
    语法:
        sudo apt install make
​
makefile 执行命令的格式:
目标文件:依赖文件列表
<TAB>cmd1
<TAB>cmd2
....
    注:每一条命令之前,必须要有一个TAB键空格(TAB键的空格需要有四格)
    makefile命令中,以#开头的行,代表注释
​
在 makefile 里面,我们可以自定义变量,且变量没有类型,通常是当作字符串来处理
    给变量赋值,通常有四种方式:
        := 简单赋值,”就地赋值“
            B:=123 //right
            B:$(A) //error,因为A没有定义
​
        =  递归赋值,”向后展开赋值“
            C=$(D) //right,D在后面有定义,C=="123"
            ...
            D:=123
​
        += 追加赋值,”在原有的基础上,在后面添加,以空格隔开“
            A:=JQY
            A+=XXF // A的内容为:"JQY XXF"
        
        ?= 条件赋值,只有当变量没有值的时候才会赋值
            A:=123
            A?=hello //A的内容为"123"
​
引用变量:
    $(变量名)
​
在makefile 里面,我们还可以使用makefile内置的变量,makefile赋予这些变量特殊的含义
    $* :表示不包含拓展名的目标文件
        eg: 目标文件:main.o   --> $* = main
​
    $@ : 表示完整的目标文件名称
        eg: 目标文件:main.o  --> $@ = main.o
​
    $^ :所有的依赖文件,以空格隔开
        eg:  依赖文件: 1.c 2.c --> $^ = 1.c 2.c
​
    $< : 表示第一个依赖文件的名称
        eg:  依赖文件: 1.c 2.c --> $< = 1.c
​
    $? :表示所有时间戳比目标文件晚的依赖文件(后面经过修改的依赖文件),以空格隔开
        eg: 依赖文件有: 1.c 2.c 3.c ,其中 1.c 3.c 都重新修改过内容
            $? = 1.c 3.c
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值