Chinaunix首页 | 论坛 | 博客
  • 博客访问: 830218
  • 博文数量: 290
  • 博客积分: 511
  • 博客等级: 下士
  • 技术积分: 1590
  • 用 户 组: 普通用户
  • 注册时间: 2010-11-29 13:14
文章分类

全部博文(290)

文章存档

2018年(28)

2017年(19)

2016年(8)

2015年(1)

2014年(14)

2013年(12)

2012年(22)

2011年(186)

分类: LINUX

2015-09-01 17:41:37

   本文的部分内容可能来源于网络,该内容归原作者所有,如果侵犯到您的权益,请及时通知我,我将立即删除,原创内容copyleft所有,使用GPL发布,可以自由拷贝,转载。但转载请保持文档的完整性,注明原作者及原链接,严禁用于任何商业用途。欢迎加入嵌入式交流群:3462094

本文主要介绍了以下内容,核心就是让大家了解嵌入式学习,本教程配有视频、文档,大家可以把文档下载下来,里面我的联系方式,包括视频地址等等,想看视频,可以移步到我的优酷视频空间。

?1、嵌入式系统概述
?2、嵌入式开发流程
?3、嵌入式学习步骤及相关参考
?4、Linux设备驱动预览


1-嵌入式系统介绍.pdf

 

?       嵌入式系统介绍

?         Tingkman出品

?       目录 

?  1、嵌入式系统概述

?  2、嵌入式开发流程

?  3、嵌入式学习步骤及相关参考

?  4Linux设备驱动预览

?   1、嵌入式系统概述

            典型嵌入式系统                                计算机

1、嵌入式系统:

     以应用为中心,以计算机技术为基础,软硬件可裁剪,适应应用系统对功能、可靠性、成本、体积、功耗等严格要求的专用计算机系统。

?   2、嵌入式开发流程

     在介绍开发流程之前,先了解一些嵌入式系统所涉及的相关概念:

    包括宿主机、目标板、交叉编译链、虚拟机、bootloader、内核、文件系统、Makefile、驱动、操作系统、上层、底层、体系结构。

              嵌入式产品,与普通电子产品一样,开发过程都需要遵循一些基本的流程,都是一个从需求分析到总体设计,详细设计到最后产品完成的过程,大致流程图如下:

?   2、嵌入式开发流程

       硬件设计基本上是原理图绘制、pcb绘制、发送厂家制板、板子回来后、焊接元器件、然后硬件调试,接下来就是程序下载,这个过程我们不做详细介绍。

       软件设计应该是大家更关心一些,可能还不太熟悉。嵌入式linux的开发很大一部分都是在linux系统下来完成开发的,基本流程就是

    编译bootloader –》编译内核-生成文件系统-编译应用程序

    下载bootloader-下载内核-下载文件系统-下载应用程序

?   2、嵌入式开发流程

上面提到很多概念:

Bootloader在嵌入式操作系统中,BootLoader是在操作系统内核运行之前运行。可以初始化硬件设备、建立内存空间映射图,从而将系统的软硬件环境带到一个合适状态,以便为最终调用操作系统内核准备好正确的环境,在嵌入式开发中,bootloader 还有一个功能就是下载内核和文件系统,常用的bootloader u-boot ViVired boot

内核:是一个操作系统的核心。是基于硬件的第一层软件扩充,提供操作系统的最基本的功能,是操作系统工作的基础,它负责管理系统的进程、内存、设备驱动程序、文件和网络系统,决定着系统的性能和稳定性

文件系统:是操作系统用于明确存储设备(常见的是磁盘,也有基于NAND Flash的固态硬盘)或分区上的文件的方法和数据结构;即在存储设备上组织文件的方法。操作系统中负责管理和存储文件信息的软件机构称为文件管理系统,简称文件系统

?   2、嵌入式开发流程

      那么首先就是开发环境,也就是开发用的工具,比方说我们开发51单片机,使用的是keil软件,这个软件就算是51的开发环境,它可以编写代码,编译代码生成目标镜像下载到板子,我们使用的codewarrior 7.1nios idevisualdsp++ 均是相应的开发环境。那么嵌入式linux的开发环境,一般是linux,比如Ubuntu Fedora CentOS Red Hat Linux

               一般开发者使用的是windows系统,但是开发linux需要linux系统,那么这时候虚拟机是一个很好的选择。

         虚拟机:  虚拟机(Virtual Machine)指通过软件模拟的具有完整硬件系统功能的、运行在一个完全隔离环境中的完整计算机系统。

        windows下使用虚拟软件虚拟一个linux系统。

   编译u-boot、内核:

      编译需要交叉编译链,交叉编译简单地说,就是在一个平台上生成另一个平台上的可执行代码。这里需要注意的是所谓 平台,实际上包含两个概念:体系结构(Architecture)、操作系统(Operating System)。同一个体系结构可以运行不同的操作系统;同样,同一个操作系统也可以在不同的体系结构上运行。举例来说,我们常说的x86 Linux平台实际上是Intel x86体系结构和Linux for x86操作系统的统称;而x86 WinNT平台实际上是Intel x86体系结构和Windows NT for x86操作系统的简称。

?   2、嵌入式开发流程

        芯片厂商一般提供做好的交叉编译链,不需要我们自己去编译交叉编译链,其实,对于开发者来讲,最好自己去编译交叉编译链,这样对编译方法会有更深入的了解。

   

    1)准备好源码、交叉编译链,准备开始编译

    2)执行make 命令就可以对源码进行编译了,编译后会产生目标文件。

    Makefile 一个工程中的源文件不计其数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作,因为 makefile就像一个Shell脚本一样,其中也可以执行操作系统的命令。

    3)编译ubootkernelrootfs、应用程序 ,下载到板子上,重启,一个典型的嵌入式系统就完成了。

?   2、嵌入式开发流程

?   2、嵌入式开发流程

?   3、嵌入式学习步骤及相关参考

 一、熟悉linux系统应用:命令+服务搭建(一个月)

    参考视频:

    IT播吧 - 寒冰老师 - 零起点学习Linux系列培训视频教程 61 

    下载地址:

    参考书籍:鸟哥的linux私房菜基础学习

   

        零起点学习linux系列课程计划表:
1讲了解linux   2讲基础操作    3讲文件          4讲目录
5讲过滤器、输入输出及管道     6讲文件查找与文件管理
7vi编辑器    8BASH    9讲系统监视   10讲用户管理
11讲硬件配置与管理   12讲文件系统第13讲计划任务    14RPM 包及其管理  15sed,awk,和其他语言  16linux开机与启动
17讲基础网络配置   18讲服务   19讲系统安全
20讲网络安全    21讲怎么使用源码安装一些软件
22讲介绍access control list ACL

获取知识:linux的由来,linux 常用命令、服务搭建

 

?   3、嵌入式学习步骤及相关参考

 二、ARM 嵌入式入门了解( 2 周)

         参考书籍:

         ARM 嵌入式 Linux 系统开发从入门到精通

    

     获取知识:深入了解交叉编译链的生成、

     初步了解arm体系结构、初步了解bootloader

     初步了解uboot移植、内核移植、文件系统移植

     初步了解设备驱动、上层应用开发QT

?   3、嵌入式学习步骤及相关参考

 三、嵌入式c语言( 1个月)

     linux 基本上是由c语言编写的,所以c语言必须要

         学会

         参考书籍:

          Linux C编程从初学到精通(华清远见)

    

     获取知识:学会使用c语言

?   3、嵌入式学习步骤及相关参考

 四、动手移植uboot、内核、文件系统( 1个月)

         软件开发,实践很重要,嵌入式学习也不例外。

          这里首先得有一个开发板,市面上很多,随便买个

          按照里面的步骤一步一步都做做。

          参考视频:

          国嵌、华清远见嵌入式培训视频

    

         获取知识:亲身体会嵌入式开发步骤。

?   3、嵌入式学习步骤及相关参考

 五、linux环境高级编程(2周)

                linux驱动、内核编程针对嵌入式初学者来讲是

        比较难的 刚入门的也不适合我们先去学习,这个

         时候建议大家先去 学习一下稍微简单的编程,那

         就是linux环境高级编程

         参考书籍:

         unix环境高级编程

         本书是被誉为UNIX编程“圣经”,可想这本书的含金量。

     获取知识:linux应用编程基础,初步了解进程、线程、信号、进程间

     通信、套接字等相关操作系统相关的知识和相关编程方法。

?   3、嵌入式学习步骤及相关参考

 六、linux驱动(n年)

          学习完高级编程后可以学习linux驱动了

          参考书籍:

          Linux设备驱动开发详解(宋宝华)

          Linux 设备驱动程序(科波特著)简称LDD

          精通Linux设备驱动程序开发

     3本书还是比较不错的,是那种可以当字典查看的书籍

     获取知识:初步了解linux驱动的分类以及驱动模型、驱动   的编写方法。

?   3、嵌入式学习步骤及相关参考

 五、linux内核(n年)

               了解完linux驱动的同时,还要去学习linux内核,学习内核的同时,最好学习一下数据结构

        参考书籍:

          深入理解LINUX内核    简称ULK

          深入Linux内核架构

          数据结构与算法分析

    获取知识:初步了解linux内核,包括进程管理和调度、内存管理、锁与进程间通信、设备驱动程序、模块、虚拟文件系统、网络、页缓存和块缓存、数据同步等等。

?   4 Linux设备驱动预览

?   4 Linux设备驱动预览

 

              

       

?   4 Linux设备驱动预览

 驱动大分类如下:

1、字符设备

2、块设备

3、网络设备

区别:

?          (1) 字符设备:提供连续的数据流,应用程序可以顺序读取,通常不支持随机存取。相反,此类设备支持按字节/字符来读写数据。举例来说,调制解调器是典型的字符设备。

?          (2) 块设备:应用程序可以随机访问设备数据,程序可自行确定读取数据的位置。此外,数据的读写只能以块(通常是512B)的倍数进行,与字符设备不同,块设备并不支持基于字符的寻址。

?          (3)网络设备是面向数据包的接收和发送而设计的。它并不对应于文件系统(/dev目录下)的节点,而是由系统分配一个唯一的名字(如eth0)。

?   4 Linux设备驱动预览

 驱动分类子系统如下:

1、字符设备驱动程序 如:cmos rtc子系统,混杂设备驱动,伪字符设备

2、串行设备驱动程序 如:UART驱动程序,TTY驱动程序

3、输入设备驱动程序 如:键盘、鼠标、触摸控制器,加速度控制器、输出事件

4I2C子系统  如:I2C核心、EEPROM

5SPI子系统

6PCMCIACF 如: PCMCIA核心、PCMCIA

7PCI

8USB子系统 如:大容量存储设备、usb串行端口转换、蓝牙、gadget驱动

9、视频子系统 如:桢缓冲API及驱动程序、控制台驱动程序

10、音频子系统 如:MP3

11、块设备驱动程序

12、网络接口卡驱动

13、无线设备驱动 如:蓝牙、红外、wifi、蜂窝网络

14、存储技术设备 如:NORFLASHNANDFLASHMTD子系统

15、其他 如:ACPIISAMCA、火线、智能输入\输出

     业余无线电、VOIP、高速互联

?   4 Linux设备驱动预览

驱动实例:

  Linux驱动程序都是以模块的形式存在的,所以我们称之为驱动模块。

  字符设备驱动(最简单的驱动)

       #include

       #include

       #include

       #include

       #include

       #include
MODULE_LICENSE("GPL");
MODULE_AUTHOR("leander");
#define MINIOR_NUM 0
#define DEVICE_SUM 1
#define MAJOR_NUM 254 /* major device number */
#define MINOR_NUM 0 /* minor device number */
static int globalvar_open(struct inode *inode, struct file *filp);
static int globalvar_release(struct inode *, struct file *filp);
static ssize_t globalvar_read(struct file*, char*, size_t, loff_t*);
static ssize_t globalvar_write(struct file*, const char*, size_t, loff_t*);


?   4 Linux设备驱动预览

驱动实例:

    字符设备驱动(最简单的驱动)

       /* the major device number */
static int globalvar_major = MAJOR_NUM;
static int globalvar_minor = MINOR_NUM;
/* init the file_operations structure */
struct file_operations globalvar_fops =
{
    .owner = THIS_MODULE,
    .open = globalvar_open,
    .release = globalvar_release,
    .read = globalvar_read,
    .write = globalvar_write,
};

/* define a cdev device */
struct cdev *cdev;

static int global_var = 0; /* global var */

?   4 Linux设备驱动预览

驱动实例:

    字符设备驱动(最简单的驱动)

      
/* module init */
static int __init globalvar_init(void)
{
    int ret = 0;
    dev_t devno = MKDEV(MAJOR_NUM, MINOR_NUM);
    cdev = cdev_alloc();

    /* register the device driver */
    /*ret = alloc_chrdev_region(MAJOR_NUM, "globalvar", &globalvar_fops);*/
    if(register_chrdev_region(devno, DEVICE_SUM, "globalvar"))
    {
        /* register fail, so use automatic allocate */
        if(alloc_chrdev_region(&devno, globalvar_minor, DEVICE_SUM, "globalvar"))
            printk("globalvar register failure.\n");
        globalvar_major = MAJOR(devno);
    }
    else
    {

?   4 Linux设备驱动预览

驱动实例:

    字符设备驱动(最简单的驱动)
        /*
         * cdev_init should be use if use the way of static statement.
         * struct cdev cdev;
         * cdev_init(&cdev, &globalvar_fops);
         * cdev.owner = THIS_MODULE;
         *
         * if using dymatic allocation.
         * struct cdev *cdev;
         * cdev = cdev_alloc();
         * cdev->owner = THIS_MODULE;
         * cdev->ops = &globalvar_fops;
         */

        cdev->owner = THIS_MODULE;
        cdev->ops = &globalvar_fops;
        if ((ret = cdev_add(cdev, devno, 1)))
            printk(KERN_NOTICE "Error %d adding globalvar.\n", ret);
        else
            printk("globalvar register success.\n");
    }

?   4 Linux设备驱动预览

驱动实例:

    字符设备驱动(最简单的驱动)

    return ret;
}

/* module exit */
static void __exit globalvar_exit(void)
{
    dev_t devno = MKDEV(globalvar_major, 0);

    /* remove cdev from kernel */
    cdev_del(cdev);

    /* unregister the device driver */
    unregister_chrdev_region(devno, 1);

    /* free the dev structure */
    if(cdev)
        kfree(cdev);
    cdev = NULL;
}

?   4 Linux设备驱动预览

驱动实例:

    字符设备驱动(最简单的驱动)

/* open device */
static int globalvar_open(struct inode *inode, struct file *filp)
{
    int ret = 0;
    printk("open success.\n");
    return ret;
}

/* release device */
static int globalvar_release(struct inode *inode, struct file *filp)
{
    printk("release success.\n");
    return 0;
}

?   4 Linux设备驱动预览

驱动实例:

    字符设备驱动(最简单的驱动)

/* read device */
static ssize_t globalvar_read(struct file *filp, char *buf, size_t len, loff_t *off)
{
    printk("reading...\n");
    if(copy_to_user(buf, &global_var, sizeof(int)))
    {
        return -EFAULT;
    }
    return sizeof(int);
}

/* write device */
static ssize_t globalvar_write(struct file *filp, const char *buf, size_t len, loff_t *off)
{
    printk("writing...\n");
    if(copy_from_user(&global_var, buf, sizeof(int)))
    {
        return -EFAULT;
    }

?   4 Linux设备驱动预览

驱动实例:

    字符设备驱动(最简单的驱动)
    return sizeof(int);
}

/* module register */
module_init(globalvar_init);
module_exit(globalvar_exit);

2
Makefile文件
#
# Makefile -- for driver
#

module=globalvar

ifneq ($(KERNELRELEASE),)
    obj-m := ${module}.o
else
    KERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
default:

?   4 Linux设备驱动预览

驱动实例:

    字符设备驱动(最简单的驱动)

    $(MAKE) -C $(KERNELDIR) M=$(PWD) modules
clean:
    rm -f *.o *.ko *.mod.c *~
insmod:
    sudo insmod ${module}.ko
    dmesg | tail
rmmod:
    sudo rmmod ${module}
    dmesg | tail
endif

3
、测试程序
/*
 * test.c -- a test file for globalvar reading and writing
 */

#include 
#include 


?   4 Linux设备驱动预览

驱动实例:

    字符设备驱动(最简单的驱动)
int main(void)
{
    int fd, num;
    /*打开"/dev/globalvar"*/
    fd = open("/dev/globalvar", O_RDWR, S_IRUSR | S_IWUSR);
    if (fd != -1 )
    {
        /*初次读globalvar*/
        read(fd, &num, sizeof(int));
        printf("The globalvar is %d\n", num);

        /*globalvar*/
        printf("Please input the num written to globalvar\n");
        scanf("%d", &num);
        write(fd, &num, sizeof(int));

        /*再次读globalvar*/
        read(fd, &num, sizeof(int));
        printf("The globalvar is %d\n", num);

        /*关闭"/dev/globalvar"*/
        close(fd);
  

?   4 Linux设备驱动预览

驱动实例:

    字符设备驱动(最简单的驱动)

    else
    {
        /* if not sudo, maybe come here */
        printf("Device open failure\n");
    }

    return 0;


}




?   4 Linux设备驱动预览

驱动实例:

    字符设备驱动(最简单的驱动)

模块入口函数:

module_init(globalvar_init);

模块退出函数:

module_exit(globalvar_exit);

模块操作函数: struct file_operations globalvar_fops =
{
    .owner = THIS_MODULE,
    .open = globalvar_open,
    .release = globalvar_release,
    .read = globalvar_read,
    .write = globalvar_write,
};

上层应用编程:上面的测试程序

 使用 fd = open("/dev/globalvar", O_RDWR, S_IRUSR | S_IWUSR);

会调用模块的globalvar_open

 写函数write(fd, &num, sizeof(int))会调用globalvar_write

读函数read(fd, &num, sizeof(int));会调用globalvar_read




?   4 Linux设备驱动预览

驱动实例:

    字符设备驱动(最简单的驱动)
上面这样一个简单的驱动程序实现了我们平时编程的习惯,

Open read write

       要实现一个字符设备驱动,就要实现上面驱动所使用的相关函数,这些函数,都需要我们平时记忆。

        打个比方说,module_init(globalvar_init);函数难度相当于1+1=2

         一个字符设备驱动就相当于  2+3=5一样

        可以想象,还有很多其他驱动程序,都有各自的规则和函数,而且复杂度远高于这个字符设备,

         驱动程序各自的规则和函数,理解起来需要时间,上面的字符设备驱动程序还没有涉及硬件,驱动程序的规则和硬件设备各自的特性这两个方面,是它不能在短时间学习的主要原因。




阅读(1069) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~