• 《嵌入式程序设计》第三、四周学习总结


    《嵌入式程序设计》第三、四周学习总结

    这两周主要学习了Linux交叉开发环境的搭建和bootloader的配置移植及编译,以及Linux的内核

    教材学习内容总结

    一.交叉开发环境的搭建
    1.交叉编译器的完整安装需要多个软件,包括binutils、gcc、glibc等软件。其中,gcc用来生成交叉编译器的,主要生成arm-linux-gcc交叉编译工具,生成此工具后已经搭建起了交叉编译环境,可以编译linux内核,但由于没有提供标准用户函数库,用户程序还无法编译;glibc主要是提供用户程序所使用的一些基本的函数库。这样交叉环境就搭建起来了。
    二、编译嵌入式Linux内核
    (1)内核配置
    内核配置中的选项主要是用户用来为目标选择处理器架构的选项,不同的处理器架构会有不同的处理器选项,ARM必须确保在根目录中makefile里“ARCH”的值已设定了目标版的类型。
    如:ARCH :=arm
    (2)内核支持的4种不同的配置方法
    这几种方法只是与用户交互界面不同,其实现的功能一样。每种方法都会通过读入一个默认的配置文件--根目录下“.config”隐藏文件
    make config基于文本的最为传统的配置界面
    make menuconfig基于文本选单的配置界面,字符终端下推荐使用
    make xconfig基于图形窗口模式的配置界面,Xwindow下推荐使用。
    make oldconfig自动读入".config"配置文件,并且只要求用户设定前次没有设定过的选项
    注意:2.4和2.6内核在串口命令上的一个重要区别,在2.4内核中"COM1"对应的是"ttyS0",而在2.6内核中"COM1"对应"ttySAC0",因此在启动参数的子项要格外注意。
    (3)建立依赖关系通常在第一次编译内核的时候进行,它会在内核源码树中每个子目录产生一个".depend"文件。运行"make dep"即可,在编译2.6版本直接输入"make"即可。

    (4)Linux内核源码目录结构
    ①/include:子目录包含了建立内核代码时所需的大部分包含文件,这个模板利用其它模板重建内核。
    ②/init:子目录包含了内核的初始化代码,这里的代码是内核工作的起始入口。
    ③/arch:子目录包含了所有处理器体系结构特定的内核代码
    ④/drivers:子目录包含了内核中所有的设备驱动程序,如块设备和SCSI设备
    ⑤/fs:子目录包含了所有的文件系统的代码
    ⑥/net子目录包含了内核的网络相关代码
    ⑦/mm子目录包含了所有内存管理代码
    ⑧/ipc子目录包含了进程间通信代码
    ⑨/kernel子目录包含了内核核心代码
    (5)将工具链加入到PATH中:
    (PATH,查看/usr/bin 第一种:)export PATH=$PATH:/usr/local/arm/gcc-3.4.6-glibc-2.3.6/bin
    这种方法关掉客户端就没了
    第二种:添加到下面三个文件其一均可
    /etc/profile是系统启动过程执行的一个脚本,对所有用户都生效。
    /.bash_profile是用户的脚本,在用户登录时生效。
    ~/.bashrc也是用户的脚本,在~/.bash_profile中调用生效。
    三.U-Boot移植配置
    (1)U-Boot源码结构
    ①board:和一些已有开发板有关的代码,如makefile和U-Boot.lds
    ②common:与体系结构无关的代码,用来实现各种命令的C程序
    ③cpu:包含CPU相关代码,其中的子目录都是以U-BOOT所支持的CPU为名,如子目录arm926ejs等
    ④disk:disk驱动的分区相关代码
    ⑤doc:文档
    ⑥drivers:通用设备驱动程序,比如各种网卡、支持CFI的Flash
    ⑦fs:支持文件系统的文件
    ⑧include:头文件,还有对各种硬件平台支持的汇编文件
    ⑨net:与网络有关的代码
    ⑩lib_arm:与ARM体系结构相关的代码
    ⑪tools:创建S-Rccord格式文件和U-BOOT image的工具
    (2)U-Boot移植主要步骤
    ①建立自己的开发版类型
    在Makefile文件中添加两行

    @$(MKCONFIG) $(@:_config=) arm arm920t eduk2410 NULL s3c24x0```
    其中"arm"为表示处理器体系结构的种类,"arm920t"表示处理器体系结构的名称 eduk2410为主板名
    ②在board目录中建立eduk2410目录,将smdk目录中的内容复制到该目录中
    ③修改GPIO配置
    修改0x00044555改为0x0004455A:
    (3)编译U-Boot
    ①首先运行如下命令配置U-Boot:
      ``` # make eduk2410_config```
        Configuring for edul2410 board...
    ②然后运行make命令编译:
         make
    四.基本文件操作
    ①open()函数用于打开或创建文件
    ②close()函数用于关闭一个被打开的文件
    ③read()函数用于将从指定的文件描述符中读出的数据放到缓冲区中,并返回实际读入的字符数。
    ④write()函数用于向打开的文件写数据,写操作从文件的当前指针位置开始。
    ⑤lseek()函数用于在指定的文件描述符中将文件指针定位到相应的位置。它只能用在可定位(可随机访问)文件操作中。
    
    
    
    ##课后作业总结
    
    (1)创建src_file文件
    ![](http://images2015.cnblogs.com/blog/1150838/201705/1150838-20170514141105707-311130575.png)
    
    (2)创建copy_file.c文件
    ![](http://images2015.cnblogs.com/blog/1150838/201705/1150838-20170514141113535-1430944513.png)
    
    (3)进行编译
    ![](http://images2015.cnblogs.com/blog/1150838/201705/1150838-20170514141118754-1070300099.png)
    (4)运行
    ![](http://images2015.cnblogs.com/blog/1150838/201705/1150838-20170514141237535-1088579765.png)
    
    (5)dest_file文件内容跟src_file一致
    
    ![](http://images2015.cnblogs.com/blog/1150838/201705/1150838-20170514141315082-171531451.png)
    
    (6)代码注释
    
    
    

    /* copy_file.c */

    // 加入头文件

    include <unistd.h>

    include <sys/types.h>

    include <sys/stat.h>

    include <fcntl.h>

    include <stdlib.h>

    include <stdio.h>

    // 每次读写缓存大小,影响运行效率

    define BUFFER_SIZE 1024

    // 源文件名

    define SRC_FILE_NAME "src_file"

    // 目标文件名

    define DEST_FILE_NAME "dest_file"

    // 复制的数据大小

    define OFFSET 10240

    int main()
    {
    // 定义源文件和目标文件
    int src_file, dest_file;
    // 定义数据的缓存区
    unsigned char buff[BUFFER_SIZE];
    // 定义数据长度
    int real_read_len;

    // 以只读方式打开源文件
    src_file = open(SRC_FILE_NAME, O_RDONLY);

    // 以只写方式打开目标文件,若此文件不存在则创建该文件,访问权限值为644
    dest_file = open(DEST_FILE_NAME, O_WRONLY | O_CREAT,
    S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
    // 如果源文件或目标文件没有,输出“ Open file error ”
    if(src_file < 0 || dest_file < 0)
    {
    printf("Open file error ");
    exit(1);
    }

    // 将源文件的读写指针移到最后10KB的起始位置
    lseek(src_file, -OFFSET, SEEK_END);

    // 读取源文件的最后10KB数据并写到目标文件中,每次读写1KB
    while((real_read_len = read(src_file, buff, sizeof(buff))) > 0)
    {
    //将数据写到dest_file文件里
    write(dest_file, buff, real_read_len);
    }
    // 关闭目标文件
    close(dest_file);
    // 关闭源文件
    close(src_file);
    return 0;
    }

    
    
    ##实验楼
    [BootLoader配置移植及编译实验](https://www.shiyanlou.com/courses/reports/1274688)
    
    ## 学习进度条
    
    |            | 代码行数(新增/累积)| 博客量(新增/累积)|学习时间(新增/累积)|重要成长|
    | --------    | :----------------:|:----------------:|:---------------:  |:-----:|
    | 目标        | 5000行            |   15            | 20/20             |       |
    | 第一周      | 200/200           |   2/2            | 1/1             |vi的使用       |
    | 第二周      | 1000/1200          |   3/7           | 7/8             |gcc,gdb,makefile       |
    | 第三周      | 500/1700          |   1/8           | 4/12             |U-Boot      |
    | 第四周      | 1500/3200        |   1/9           | 6/18             |Linux的内核      |
    
    ## 参考资料
    -  《交叉环境编译PPT》
    -  《嵌入式Linux应用程序开发标准教程》
  • 相关阅读:
    say goodbye to Heroku All In One
    Next.js Conf Ticket All In One
    如何在 macOS 上使用 iMovie 进行视频剪辑教程 All In One
    河流水质等级 All In One
    Leetcdoe 2037. 使每位学生都有座位的最少移动次数(可以,一次过)
    Leetcode 2190. 数组中紧跟 key 之后出现最频繁的数字(可以,一次过)
    Leetcode 2164. 对奇偶下标分别排序(可以,一次过)
    C++ std::function的用法
    利用torch.nn实现前馈神经网络解决 回归 任务
    pytorch 中 torch.nn.Linear() 详解
  • 原文地址:https://www.cnblogs.com/qiaoye06/p/6848962.html
Copyright © 2020-2023  润新知