Linux2_6内核下同步串行通信驱动的开发与应用

合集下载

Linux2.6内核中的Framebuffer驱动程序设计

Linux2.6内核中的Framebuffer驱动程序设计

Linux2.6内核中的Framebuffer驱动程序设计虽然Framebuffer驱动技术在PC上已经逐渐被淘汰,但是在嵌入式等考虑成本的平台下,由于其使用简单,成本低廉的优势,使用相当的广泛。

在Linux2.4和Linux2.6内核之间,Framebuffer的框架结构发生了很大的变化,网络上很多介绍Framebuffer的文档都是基于2.4内核下的,这就使得在2.6内核开发Framebuffer驱动增加了难度,本文介绍2.6内核下如何编写Framebuffer驱动,以适应最新版本的Linux。

Framebuffer是出现在Linux 2.2.xx及以后版本内核当中的一种驱动程序接口,这种接口将显示设备抽象为帧缓冲区设备。

帧缓冲区为图像硬件设备提供了一种抽象化处理,它代表了一些视频硬件设备,允许应用软件通过定义明确的界面来访问图像硬件设备。

这样软件无须了解任何涉及硬件底层驱动的东西(如硬件寄存器)。

它允许上层应用程序在图形模式下直接对显示缓冲区进行读写和I/O控制等操作。

通过专门的设备节点可对该设备进行访问,如/dev/fb*。

用户可以将它看成是显示内存的一个映像,将其映射到进程地址空间之后,就可以进行读写操作,而读写操作可以反映到LCD。

二、 Framebuffer驱动的主要数据结构fb_fix_screeninfo记录了帧缓冲设备和指定显示模式的固件信息。

它包含了屏幕缓冲区的物理地址和长度等信息。

fb_var_screeninfo记录了帧缓冲设备和指定显示模式的可修改信息。

它包括显示屏幕的分辨率、每个像素的比特数和一些时序变量。

其中变量 xres定义了屏幕一行所占的像素数,yres定义了屏幕一列所占的像素数。

fb_info info是Linux为帧缓冲设备定义的驱动层接口。

它不仅包含了底层函数,而且还有记录设备状态的数据。

每个帧缓冲设备都与一个fb_info结构相对应。

其中成员变量包含fb_fix_screeninfo、fb_var_screeninfo这两个数据结构,另外还有Framebuffer的回调函数。

Linux kernel 2.6 USB转串口IC驱动程序介绍

Linux kernel 2.6 USB转串口IC驱动程序介绍

Linux kernel 2.6 USB转串口IC驱动程序介绍Version historyIndex Version Author Date Comment1 V1.0.0 Wen Xiaoyong 2011-12-13 Draft,Linux kernel 2.6.31(comefrom Freescale iMX515 BSP), baseon USB 2.0目录Linux kernel 2.6 USB转串口IC驱动程序介绍 (1)Version history (1)目录 (2)1. USB介绍 (3)1.1 USB的发展历史 (3)1.2 USB接口电气规范 (4)1.3 USB协议简介 (8)2. Linux kernel 2.6中,USB框架 (12)2.1 Linux kernel中的USB子系统 (12)2.2 USB转串口IC驱动架构图 (15)3. Linux kernel 2.6内核,USB接口函数 (17)4. USB转串口芯片驱动框架 (19)4.1 USB转串口芯片驱动,关键数据结构 (20)4.2 USB转串口芯片驱动接口 (23)4.3 应用程序访问I2C设备例子程序 (27)5. 参考资料 (28)5.1 参考代码 (28)5.2 参考文档 (28)1. USB介绍1.1 USB的发展历史通用串行总线(英语:Universal Serial Bus,简称“USB”)是连接计算机系统与外部设备的一个串口总线标准,也是一种输入输出接口技术规范,被广泛应用于个人电脑和移动设备等信息通讯产品,并扩展至摄影器材、数字电视(机顶盒)、游戏机等其它相关领域。

多媒体电脑刚问世时,外接式设备的传输接口各不相同,如打印机只能接LPT port、调制解调器只能接RS232、鼠标键盘只能接PS/2等。

繁杂的接口系统,加上需安装驱动程序并重启才能使用的限制,都不免造成用户的困扰。

因此,创造出一个统一且支持热插拔的外接式传输接口,便成为无可避免的趋势。

linux内核SPI总线驱动分析

linux内核SPI总线驱动分析

linux内核SPI总线驱动分析(一)下面有两个大的模块:一个是SPI总线驱动的分析(研究了具体实现的过程)另一个是SPI总线驱动的编写(不用研究具体的实现过程)SPI总线驱动分析1 SPI概述SPI是英语Serial Peripheral interface的缩写,顾名思义就是串行外围设备接口,是Motorola 首先在其MC68HCXX系列处理器上定义的。

SPI接口主要应用在EEPROM,FLASH,实时时钟,AD转换器,还有数字信号处理器和数字信号解码器之间。

SPI是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线,节约了芯片的管脚,同时为PCB的布局上节省空间,提供方便。

SPI的通信原理很简单,它以主从方式工作,这种模式通常有一个主设备和一个或多个从设备,需要4根线,事实上3根也可以。

也是所有基于SPI的设备共有的,它们是SDI(数据输入),SDO(数据输出),SCLK(时钟),CS(片选)。

MOSI(SDO):主器件数据输出,从器件数据输入。

MISO(SDI):主器件数据输入,从器件数据输出。

SCLK :时钟信号,由主器件产生。

CS:从器件使能信号,由主器件控制。

其中CS是控制芯片是否被选中的,也就是说只有片选信号为预先规定的使能信号时(高电位或低电位),对此芯片的操作才有效,这就允许在同一总线上连接多个SPI设备成为可能。

需要注意的是,在具体的应用中,当一条SPI总线上连接有多个设备时,SPI本身的CS有可能被其他的GPIO 脚代替,即每个设备的CS脚被连接到处理器端不同的GPIO,通过操作不同的GPIO口来控制具体的需要操作的SPI设备,减少各个SPI设备间的干扰。

SPI是串行通讯协议,也就是说数据是一位一位从MSB或者LSB开始传输的,这就是SCK时钟线存在的原因,由SCK提供时钟脉冲,MISO、MOSI则基于此脉冲完成数据传输。

SPI支持4-32bits的串行数据传输,支持MSB和LSB,每次数据传输时当从设备的大小端发生变化时需要重新设置SPI Master的大小端。

Linux内核同步机制简介分析

Linux内核同步机制简介分析

Linux内核同步机制简介1 介绍1)由于现代Linux操作系统是多任务、SMP、抢占式以及中断是异步执行的,导致共享资源容易被并发访问,从而使得访问共享资源的各线程之间互相覆盖共享数据,造成被访问数据处于不一致状态,因此Linux提供了同步机制来防止并发访问。

2)常用的同步机制(如自旋锁)用来保护共享数据使用起来简单有效,但由于CPU的处理速度与访问内存的速度差距越来越大,导致获取锁的开销相对于CPU的速度在不断的增加。

因为这种锁使用了原子操作指令,需要原子地访问内存,即获取锁的开销与访问内存的速度相关。

3)Linux内核根据对不同共享资源的特性,提供多种同步机制:原子操作、自旋锁、读-写自旋锁、信号量、读-写信号量、完成变量、顺序锁、禁止抢占、内存屏障及RCU,本文将对其分别进行简要介绍。

2 原子操作(atomic)2.1 基本原理1)所谓原子操作,就是该操作绝不会在执行完毕前被任何其它任务或事件打断,它是最小的执行单位,不可能有比它更小的执行单位。

2)原子操作通常是内联函数,通过内联汇编指令来实现。

3)原子操作需要硬件的支持,因此不同的体系结构的实现方式不同。

4)内核提供了两组原子操作接口:整数操作和位操作。

2.1.2 原子整数操作1)原子操作主要用于实现资源计数,很多引用计数就是通过原子操作实现的。

2)原子类型定义如下:(参看RHEL6.5GA_x86_64内核文件:/root/include/linux/types.h)3)针对整数的原子操作只能对atomic_t类型的数据进行处理,原因如下:a)让原子函数只接受atomic_t类型的操作数,可以确保原子操作只与这种特殊类型一起使用。

b)使用atomic_t类型确保编译器不对相应的值进行优化,使得原子操作最终接收到正确的内存地址。

c)可以屏蔽不同体系结构上实现原子操作的差异。

2.1.2 原子位操作1)位操作函数是对普通的内存地址进行操作的,对所操作的数据类型没有要求。

Linux下的串口编程(ZT)

Linux下的串口编程(ZT)

Linux下的串口编程(ZT)Linux 操作系统从一开始就对串行口提供了很好的支持,本文就 Linux 下的串行口通讯编程进行简单的介绍。

串口简介串行口是计算机一种常用的接口,具有连接线少,通讯简单,得到广泛的使用。

常用的串口是 RS-232-C 接口(又称 EIA RS-232-C)它是在 1970 年由美国电子工业协会(EIA)联合贝尔系统、 调制解调器厂家及计算机终端生产厂家共同制定的用于串行通讯的标准。

它的全名是"数据终端设备(DTE)和数据通讯设备(DCE)之间串行二进制数据交换 接口技术标准"该标准规定采用一个 25 个脚的 DB25 连接器,对连接器的每个引脚的信号内容加以规定,还对各种信号的电平加以规定。

传输距离在码元畸变小于 4% 的情况下,传输电缆长度应为 50 英尺。

Linux 操作系统从一开始就对串行口提供了很好的支持,本文就 Linux 下的串行口通讯编程进行简单的介绍,如果要非常深入了解,建议看看本文所参考的《Serial Programming Guide for POSIX Operating Systems》计算机串口的引脚说明序号 信号名称 符号 流向 功能2 发送数据 TXD DTE→DCE DTE发送串行数据3 接收数据 RXD DTE←DCE DTE 接收串行数据4 请求发送 RTS DTE→DCE DTE 请求 DCE 将线路切换到发送方式5 允许发送 CTS DTE←DCE DCE 告诉 DTE 线路已接通可以发送数据6 数据设备准备好 DSR DTE←DCE DCE 准备好7 信号地 信号公共地8 载波检测 DCD DTE←DCE表示 DCE 接收到远程载波20 数据终端准备好 DTR DTE→DCE DTE 准备好22 振铃指示 RI DTE←DCE表示 DCE 与线路接通,出现振铃串口操作串口操作需要的头文件#i nclude <stdio.h> /*标准输入输出定义*/#i nclude <stdlib.h> /*标准函数库定义*/#i nclude <unistd.h> /*Unix 标准函数定义*/#i nclude <sys/types.h>#i nclude <sys/stat.h>#i nclude <fcntl.h> /*文件控制定义*/#i nclude <termios.h> /*PPSIX 终端控制定义*/#i nclude <errno.h> /*错误号定义*/打开串口在 Linux 下串口文件是位于 /dev 下的串口一 为 /dev/ttyS0串口二 为 /dev/ttyS1打开串口是通过使用标准的文件打开函数操作:int fd;/*以读写方式打开串口*/fd = open( "/dev/ttyS0", O_RDWR);if (-1 == fd){/* 不能打开串口一*/perror(" 提示错误!");}设置串口最基本的设置串口包括波特率设置,效验位和停止位设置。

Linux2.6内核的USB鼠标驱动开发

Linux2.6内核的USB鼠标驱动开发
能用于控制USB设备的局部结构体。通常需要探 测没备的端口地址和缓冲区大小,因为需要它们才 能和设备通信。对于鼠标驱动程序来说,首先要访 问端口,查看端口的方向,类型,这是通过查看struct usb_endpoint_descriptor的bEndpointAddress和bmAt— tributes的值是否匹配来完成的。相关代码如下:
No.5 Oct..2008
微处理机
MICROPROCESSORS
第5期 2008年10月
Linux2.6内核的USB鼠标驱动开发
杨春霞,王自强 (南京大学电子工程系,南京210093)
摘要:主.6内核较先前版本有很大程度的修改。首先介绍2.6内核的设备模型以及驱动编
写上的变化,然后介绍USB设备,以鼠标为例重点说明USB驱动程序
struct usb_device术dev;/宰相应的USB设备指针∥ unsigned int pipe;/木端口信息母/ int status;/半返回的状态信息,Ic/ void·transfer_buffer;/书指向相关数据缓冲区·/ int transfer__buffer 1e%,th;/母数据缓冲区大小木/ int actual_length;/木返回的实际数据大小木/
万方数据
5期
杨春霞等:Linux2.6内核的USB鼠标驱动开发
·95·
3 USB系统介绍及通信
USB采用四线电缆,其中两根是用来传送数据 的串行通道。另两根为设备提供电源。最新的USB 规范修订增加了高达480Mbps的高速连接。
USB系统采用级联星型拓扑,该拓扑由三个基 本部分组成:主机(Host),集线器(Hub)和功能设 备。USB主控制器负责询问每个USB设备是否有 数据需要发送。

Linux2.6下内核调试技术的改进与研究

Linux2.6下内核调试技术的改进与研究
合 . 法 轻易 的将 内核 代码 放 在 调试 程 序 中执 行 和 无 跟 踪 。 因而在 编 写 驱动 程 序之 前 . 们 首 先编 译 并 我
安 装 自己的新 内核 . 是 为 了在 内核 代 码 中加 入 以 这
收 稿 日期: 0 5 0 — 9 20— 80 基 金 项 目: 安 部 金 盾 工 程 资 助 项 目 (1 A 2W0 3 公 JG B 3 1 )
Ab ta t Ac o dn h iu d l c a im n e ied e ’ lme t. hsp p ra ay e e k re e sr c : cr igt te Ln xmo ue me h ns a dd vc dv rsee ns ti a e lBst e l - o n h n d b gp be i ed vc r e ’ e eo me tpo e s n d rsac e e k r e e u c n lg o gd , a - u r lm n t e ied v rsd v lp n rc s,a ee rh st en l b gt h oo yt mu lyme o h i h d e h n w i ,rp ssa mp o e ou o b u mo alc t nma a e n d ac s ntek r e. hl p o oe i rv dslt n a o t e n i me w l ai , n g me ta ce si e 1 o o n h n Ke r s Ln x26 De u e h oo y K o d ywo d : iu ., b g tc n lg , ig
YANG o Ma ,DAIZib n - i
( stt o lc o i T cn lg,h L fr ai n ier g nvri , hnzo 5 0 4C ia I tue f et nc eh o y teP AI om t nE g ei i sy Z e ghu4 0 0 hn ) ni E r o n o n nU e t

Linux内核架构和工作原理详解

Linux内核架构和工作原理详解

Linux内核架构和工作原理详解作用是将应用层序的请求传递给硬件,并充当底层驱动程序,对系统中的各种设备和组件进行寻址。

目前支持模块的动态装卸(裁剪)。

Linux内核就是基于这个策略实现的。

Linux 进程采用层次结构,每个进程都依赖于一个父进程。

内核启动init程序作为第一个进程。

该进程负责进一步的系统初始化操作。

init进程是进程树的根,所有的进程都直接或者间接起源于该进程。

virt/ ---- 提供虚拟机技术的支持。

Linux内核预备工作理解Linux内核最好预备的知识点:懂C语言懂一点操作系统的知识熟悉少量相关算法懂计算机体系结构Linux内核的特点:结合了unix操作系统的一些基础概念Linux内核的任务:1.从技术层面讲,内核是硬件与软件之间的一个中间层。

作用是将应用层序的请求传递给硬件,并充当底层驱动程序,对系统中的各种设备和组件进行寻址。

2.从应用程序的层面讲,应用程序与硬件没有联系,只与内核有联系,内核是应用程序知道的层次中的最底层。

在实际工作中内核抽象了相关细节。

3.内核是一个资源管理程序。

负责将可用的共享资源(CPU时间、磁盘空间、网络连接等)分配得到各个系统进程。

4.内核就像一个库,提供了一组面向系统的命令。

系统调用对于应用程序来说,就像调用普通函数一样。

内核实现策略:1.微内核。

最基本的功能由中央内核(微内核)实现。

所有其他的功能都委托给一些独立进程,这些进程通过明确定义的通信接口与中心内核通信。

2.宏内核。

内核的所有代码,包括子系统(如内存管理、文件管理、设备驱动程序)都打包到一个文件中。

内核中的每一个函数都可以访问到内核中所有其他部分。

目前支持模块的动态装卸(裁剪)。

Linux内核就是基于这个策略实现的。

哪些地方用到了内核机制?1.进程(在cpu的虚拟内存中分配地址空间,各个进程的地址空间完全独立;同时执行的进程数最多不超过cpu数目)之间进行通信,需要使用特定的内核机制。

Linux_终端控制台体系及串口驱动分析

Linux_终端控制台体系及串口驱动分析

Linux终端控制台体系及串口驱动分析数据通信的基本方式可分为并行通信与串行通信两种:并行通信:利用多条数据线路将数据的各位同时传送。

它的特点是传输速度快,适用于短距离通信。

串行通信:利用一条数据线将数据一位位顺序传送。

特点是通信线路简单,利用简单的线缆就可实现通信,低成本,适用于远距离通信。

异步通信以一个字符为传输单位,通信中的两个字符间的时间间隔是不固定的,然而同一个字符中的两个相邻位之间的时间间隔是固定的。

通信协议:是指双方约定的一些规则。

在使用异步串口传送一个字符信息时,对数据格式有如下规定:规定有空闲位、起始位、资料位、奇偶校验位、停止位。

起始位:先发一个逻辑“0”信号,表示传输字符的开始数据位:紧接在起始位之后。

数据位的个数可以是4、5、6、7、8,从最低位开始传送,靠时钟定位。

奇偶校验位:数据位加上这一位后,使得“1”的位数应为偶数(偶校验)或奇数(奇校验),以此校验数据传送的正确性。

停止位:它是一个字符数据的结束标志。

空闲位:处于逻辑“1”状态,表示当前线路上没有数据传送。

波特率:是衡量数据传送速率的指针。

表述每秒钟传送的二进制位数。

注:异步通信是按字符传输的,接收设备在收到起始信号之后在一个字符的传输时间内能和发送设备保持同步就能正确接收。

传送方式:单工方式、半双工方式、全双工方式终端概述:在Linux中,TTY(终端)是一类字符设备的统称,它包括了3种类型:控制台、串口和伪终端。

控制台:供内核使用的终端为控制台。

控制台在Linux启动时,通过命令console=…指定,如果没有指定控制台,系统把第一个注册的终端(tty)作为控制台。

1、控制台是一个虚拟的终端,它必须映射到真正的终端上。

2、控制台可以简单的理解为printk输出的地方3、控制台是个只输出的设备,功能很简单,只能在内核中访问。

伪终端:伪终端设备是一种特殊的终端设备,由主-从两个成对的设备构成,当打开主设备时,对应的从设备随之打开,形成连接状态。

Linux驱动之串口驱动程序分析

Linux驱动之串口驱动程序分析

3.6 接收中断函数uart_rx_interrupt
static void s3c2410uart_rx_interrupt(int irq, void *dev_id, struct pt_regs *regs) { struct uart_info *info = dev_id; struct tty_struct *tty = info->tty; unsigned int status, ch, max_count = 256; struct uart_port *port = info->port; status = UART_UTRSTAT(port); while ((status & UTRSTAT_RX_RDY) && max_count--) { if (tty->flip.count >= TTY_FLIPBUF_SIZE) { tty->flip.tqueue.routine((void *) tty); if (tty->flip.count >= TTY_FLIPBUF_SIZE) { printk(KERN_WARNING "TTY_DONT_FLIP set\n");
Receive Mode:选择接收模式。如果是采用DMA模式的话,还需要指 定说使用的DMA信道。 Transmit Mode :同上。 Send Break Signal :选择是否在传1帧资料中途发送Break信号。
Loopback Mode :选择是否将UART置于Loopback测试模式。 Rx Error Status Interrupt Enable :选择是否使能当发生接收异常时, 是否产生接收错误中断。 Rx Time Out Enable :是否使能接收超时中断。 Rx Interrupt Type :选择接收中断类型。 选择0:Pulse(脉冲式/边沿式中断。非FIFO模式时,一旦接收缓冲区 中有数据,即产生一个中断;为FIFO模式时,一旦当FIFO中的资料达 到一定的触发水平后,即产生一个中断) 选择1:Level(电平模式中断。非 FIFO模式时,只要接收缓冲区中有 数据,即产生中断;为FIFO模式时,只有FIFO中的资料达到触发水平 后,即产生中断) Tx Interrupt Type :类同于Rx Interrupt Type

Unux2.6环境下USB设备的驱动实现

Unux2.6环境下USB设备的驱动实现
行 研 发 的硬 件 平 台 对 该 UDC进 行 了测 试 。
关 ห้องสมุดไป่ตู้ 词 :l u 26 i x .;嵌 入 式 系统 ;设 备 控 制 器 驱 动 ;U B 动 n S驱
0 引言
嵌 入 式l u 系 统环 境 以其 易 于移 植裁 减 、内 ix n 核小 、效 率高 、完 整 、原代 码 开放 及性 能 优 异等
第2卷 年 月 l 1 2 2 0 第2 期 0
蓬舒
Vl2N. ol o _ 2
Fe b.2Ol O
d i O 9 9 .s .5 3 4 9 .0 00 .2 o: . 6 0i n1 6 - 7 52 1 .2 1 l3 s 0
U u 26 n x .环境 下U B S 设备的驱 动实现
纽 带是 一些全 局结 构体 变量 。
12 Ga g tAPI . d e
的海量 存储 设 备 、 串 口设备 、网络设 备 等设 备 驱
动程序 及各 种U B dvc控 制 器芯 片 的驱 动程序 。 S ei e 市 场上 U B 备控 制器 芯 片 种类 繁 多 ,大多 数 用 S设 户 需要 针对 特 定应 用 来 开发 相 关 的U B 备 控 制 S设 器 驱动 程序 ,才 能使 设备 正 常工 作在 l u 操 作 系 ix n
第 二层 主要 是对 操作 函数 的简单 封装 :第 三层 为 设 备驱 动层 ,可 根据 系统 的需 求 实 现所 对应 的 功
能 。 图 l 示 是 Ln xG d e子 系 统 的 驱 动 层 次 。 所 iu a gt
[i 三:
[ : 三
控器动 制驱层
图 1 G d ef 系 统 的 驱 动 层 次 a gt-

Linux内核简要介绍(doc 9页)

Linux内核简要介绍(doc 9页)

提供不同能力。

实际驱动程序设计应该是在众多需求之间的一个平衡。

例如,不同程序可以同时使用同一个设备,而驱动程序的开发者可以完全自由地决定如何处理同步机制。

你可以实现到设备上的内存映射,而完成独立于硬件的具体能力,或者你可以提供给用户函数库,帮助应用程序的程序员在可用原语的基础上实现新策略,或者诸如此类的方法。

一个很重要需要考虑的问题就是,如何在提供给用户尽可能多的选项,平衡你需要编写所花费的时间,以及为使错误尽可能少而保持代码简单之间的平衡。

如果即为同步又为异步操作设计驱动程序,如果允许同时打开多次,并且如果能够发掘所有硬件功能,而不用增加软件层“去简化事情”——例如将二进制数据转换成文本或者策略相关的操作——那就很容易编写而且很好维护了。

达成“策略无关”实际上是软件设计的共同目标。

实际上,大多数设备驱动程序是和用户程序一起发布的,这些程序可以帮助完成对目标设备的配置和访问。

这些程序可以是从简单的配置程序到完整的图形应用。

通常还要提供一个客户端库文件。

本书讨论范围是内核,所以我们不考虑策略问题,也不考虑应用程序或支持库。

有时,我们会讨论不同策略,以及如何支持这些策略,但我们不会深入到使用一定策略或设备编程需要的细节问题。

不过你应该可以理解,用户程序是一个软件包的内核,就算策略无关的软件包也会和配置文件一起发布,这些文件提供了基本机制上的缺省行为。

划分内核在Unix系统中,若干并发进程会参加不同的任务。

每个进程都要求获得系统资源,可以是计算、内存、网络连接或别的资源。

内核是一整块可执行代码,用它来负责处理所有这样的请求。

尽管在不同的内核任务之间的区别不是总能清楚地标识出来,内核的作用还是可以被划分的。

如图1-1所示,划分为如下这些部分:进程管理内核负责创建和终止进程,并且处理它们和外部世界的联系(输入和输出)。

对整个系统功能来讲,不同进程之间的通信(通过信号,管道,进程间通信原语)是基本的,这也是由内核来处理的。

(完整word版)linux下的串口通信程序详解

(完整word版)linux下的串口通信程序详解

linux下的串口通信程序详解
2009-07-19 12:37
为了说明问题,下面给出测试程序来理解linux下的串口操作流程,例程receive.c 用来接收从串口发来的数据,而例程send.c用来发送数据到串口。

二者成功建立串口连接后,串口接收端会收到串口发送端发来的字符串数据“Hello,this is a Serial Port test!”。

分别将上面的俩个程序编译之后就可以运行了,如果是在两个不同的平台上运行,比如,在开发板上运行数据发送程序write(write.c编译后得到),在宿主机上运行结收数据程序read(read.c编译得到),采用串口线将二者正确连接之后,就可以运行来看实际的效果了:
首先在宿主机端运行数据接收程序receive:
[zhang@localhost]# ./receive
[zhang@localhost]#open /dev/ttyS0: Success
ready for receiving data...
The data received is:
Hello,this is a Serial_Port test!
[zhang@localhost]#
在接收端运行完程序之后再到发送端运行数据发送程序send:
#./send
ready for sending data...
the number of char sent is 35
#
运行完发送程序之后就可以在接收端看到接收的数据了。

也可以在一台PC机上来运行这两个程序,这时需要将串口线的2、3脚短路连接即可(自发自收),实际运行的步骤与上面相同。

嵌入式Linux2.6内核的CAN驱动设计与实现

嵌入式Linux2.6内核的CAN驱动设计与实现
Ab t a t oa h e et eC sr c :T c i v AN- u e i e s di h b s v c s e e e d dk r e i u .. 4 eh do CAN- u e ie e i ni e mb d e d u n mb d e e n l n x2 62 ,a t o f L m b s v c s sg t d d n h e edd
ZHAN G e s n , W AN G n . i Xu .o g Ho g 1 , XU h o e Z a
(. co l fnoma o d lc i l n i ei , C i nvri f n gadTcn l y u h u 2 0 8 1 Sh o o Ifr t n n etc g er g hn U iesyo Mii eh o g ,X z o 10 , i a E r aE n n a t n n o 2
C ia . pr n fnom ̄ o n i e n ,X zo ol e fn uta T c ooy uh u 2 0 6 hn) h ;2 Deat t Ifr in gn r g uh uC l g Id sil eh lg,X zo 10 ,C ia n me o E ei e o r n 2
具 体步骤 、 A C N总线驱 动初始化 和 中断控制 的设计 方法 以及 C N驱 动加 载步骤 。最后通 过实例验证 了 C 总 线驱 动设计 A N A
的正确 性。
关键 词 : 嵌入 式;Lnx .;S I C N总 线;驱 动程序 iu26 P; A
中图法分类 号: P 6 . T 3 81
0 引 言
在 嵌入式领域 中,i x . Ln 26内核 除 了 提 高 其 实 时 性 能 , u 系 统地 移植 更 加 方便 , 时添 加 了新 的 体 系 结 构 和 处 理 类 型 , 同 可

嵌入式Linux2.6内核启动流程)

嵌入式Linux2.6内核启动流程)

Linux内核组成之五兆芳芳创作(国嵌)L1.解压缩2.初始化3.启动应用程序Linux内核启动流程(国嵌)—担任解压缩)Start:.type start,#function.rept 8mov r0, r0.endrb 1f.word 0x016f2818 @ Magic numbers to help the loader.word start @ absolute load/run zImage address.word _edata @ zImage end address1: mov r7, r1 @ save architecture ID mov r8, r2 @ save atags pointer这也标记取u-boot将系统完全的交给了OS,bootloader生命终止.之儿女码在133行会读取cpsr并判断是否处理器处于supervisor模式——从u-boot进入kernel,系统已经处于SVC32模式;而利用angel进入则处于user模式,还需要额定两条指令.之后是再次确认中断封闭,并完成cpsr写入mrs r2, cpsr @ get current modetst r2, #3 @ not user?bne not_angelmov r0, #0x17 @ angel_SWIreason_EnterSVCswi 0x123456 @ angel_SWI_ARMnot_angel:mrs r2, cpsr @ turn off interrupts toorr r2, r2, #0xc0 @ prevent angel from runningmsr cpsr_c, r2然后在LC0地址处将分段信息导入r0-r6、ip、sp等存放器,并查抄代码是否运行在与链接时相同的目标地址,以决定是否进行处理.由于现在很少有人不使用loader和tags,将zImage烧写到rom直接从0x0位置执行,所以这个处理是必须的(但是zImage的头现在也保存了不必loader也可启动的能力).arm架构下自解压头一般是链接在0x0地址而被加载到0x30008000运行,所以要修正这个变更.涉及到r5存放器存放的zImage基地址r6和r12(即ip存放器)存放的got(global offset table)r2和r3存放的bss段起止地址sp栈指针地址很复杂,这些存放器统统被加上一个你也能猜到的偏移地址0x30008000.该地址是s3c2410相关的,其他的ARM处理器可以参考下表PXA2xx是0xa0008000IXP2x00和IXP4xx是0x00008000TI davinci DM64xx是0x80008000TI omap系列是0x80008000AT91RM/SAM92xx系列是0x20008000Cirrus EP93xx是0x00008000这些操纵产生在代码172行开始的地方,下面只粘贴一部分add r5, r5, r0add r6, r6, r0add ip, ip, r0前面在211行进行bss段的清零任务not_relocated: mov r0, #01: str r0, [r2], #4 @ clear bssstr r0, [r2], #4str r0, [r2], #4str r0, [r2], #4cmp r2, r3blo 1b然后224行,打开cache,并为前面解压缩设置64KB的临时malloc空间bl cache_onmov r1, sp @ malloc space above stack add r2, sp, #0x10000 @ 64k max 接下来238行进行查抄,确定内核解压缩后的Image目标地址是否会笼盖到zImage头,如果是则准备将zImage头转移到解压出来的内核前面cmp r4, r2bhs wont_overwritesub r3, sp, r5 @ > compressed kernel size add r0, r4, r3, lsl #2 @ allow for 4x expansion cmp r0, r5bls wont_overwritemov r5, r2 @ decompress after mallocspacemov r0, r5mov r3, r7bl decompress_kernel真实情况——在大多数的应用中,内核编译都会把压缩的zImage和非压缩的Image链接到同样的地址,s3c2410平台下便是0x30008000.这样做的利益是,人们不必关怀内核是Image仍是zImage,放到这个位置执行就OK,所以在解压缩后zImage头必须为真正的内核让路.在250行解压完毕,内核长度前往值存放在r0存放器里.在内核末尾空出128字节的栈空间用,并且使其长度128字节对齐.add r0, r0, #127 + 128 @ alignment + stackbic r0, r0, #127 @ align the kernel length 算出搬移代码的参数:计较内核末尾地址并存放于r1存放器,需要搬移代码原来地址放在r2,需要搬移的长度放在r3.然后执行搬移,并设置好sp指针指向新的栈(原来的栈也会被内核笼盖掉)add r1, r5, r0 @ end of decompressed kerneladr r2, reloc_startldr r3, LC1add r3, r2, r31: ldmia r2!, {r9 - r14} @ copy relocation code stmia r1!, {r9 - r14}ldmia r2!, {r9 - r14}stmia r1!, {r9 - r14}cmp r2, r3blo 1badd sp, r1, #128 @ relocate the stack搬移完成后刷新cache,因为代码地址变更了不克不及让cache再命中被内核笼盖的老地址.然后跳转到新的地址持续执行bl cache_clean_flushadd pc, r5, r0 @ call relocation code注意——zImage在解压后的搬移和跳转会给gdb调试内核带来麻烦.因为用来调试的符号表是在编译是生成的,其实不知道以后会被搬移到何处去,只有在内核解压缩完成之后,按照计较出来的参数“告知”调试器这个变更.以撰写本文时使用的zImage为例,内核自解压头重定向后,reloc_start地址由0x30008360变成0x30533e60.故我们要把vmlinux的符号表也相应的从0x30008000后移到0x30533b00开始,这样gdb就可以正确的对应源代码和机械指令.随着头部代码移动到新的位置,不会再和内核的目标地址冲突,可以开始内核自身的搬移了.此时r0存放器存放的是内核长度(严格的说是长度外加128Byte的栈),r4存放的是内核的目的地址0x30008000,r5是目前内核存放地址,r6是CPU ID,r7是machine ID,r8是atags地址.代码从501行开始reloc_start: add r9, r5, r0sub r9, r9, #128 @ do not copy the stackdebug_reloc_startmov r1, r41:.rept 4ldmia r5!, {r0, r2, r3, r10 - r14} @ relocate kernelstmia r1!, {r0, r2, r3, r10 - r14}.endrcmp r5, r9blo 1badd sp, r1, #128 @ relocate the stack接下来在516行清除并封闭cache,清零r0,将machine ID存入r1,atags指针存入r2,再跳入0x30008000执行真正的内核Imagecall_kernel: bl cache_clean_flushbl cache_offmov r0, #0 @ must be zeromov r1, r7 @ restore architecture numbermov r2, r8 @ restore atags pointermov pc, r4 @ call kernel内核代码入口在arch/arm/kernel/head.S文件的83行.首先进入SVC32模式,并查询CPU ID,查抄正当性msr cpsr_c, #PSR_F_BIT | PSR_I_BIT | SVC_MODE @ ensure svc mode@ and irqs disabledmrc p15, 0, r9, c0, c0 @ get processor idbl __lookup_processor_type @ r5=procinfo r9=cpuid movs r10, r5 @ invalid processor (r5=0)? beq __error_p @ yes, error 'p'接着在87行进一步查询machine ID并查抄正当性bl __lookup_machine_type @ r5=machinfomovs r8, r5 @ invalid machine (r5=0)? beq __error_a @ yes, error 'a'其中__lookup_processor_type在linux-2.6.24-moko-linuxbj/arch/arm/kernel/head-common.S文件的149行,该函数首将标号3的实际地址加载到r3,然后将编译时生成的__proc_info_begin虚拟地址载入到r5,__proc_info_end 虚拟地址载入到r6,标号3的虚拟地址载入到r7.由于adr 伪指令和标号3的使用,以及__proc_info_begin等符号在linux-2.6.24-moko-linuxbj/arch/arm/kernel/vmlinux.lds而不是代码中被定义,此处代码不是很是直不雅,想弄清楚代码缘由的读者请耐心阅读这两个文件和adr伪指令的说明. r3和r7辨别存储的是同一位置标号3的物理地址(由于没有启用mmu,所以当前肯定是物理地址)和虚拟地址,所以儿者相减即得到虚拟地址和物理地址之间的offset.利用此offset,将r5和r6中保管的虚拟地址转变成物理地址__lookup_processor_type:adr r3, 3fldmda r3, {r5 - r7}sub r3, r3, r7 @ get offset between virt&physadd r5, r5, r3 @ convert virt addresses toadd r6, r6, r3 @ physical address space然后从proc_info中读出内核编译时写入的processor ID和之前从cpsr中读到的processor ID对比,查抄代码和CPU 硬件是否匹配(想在arm920t上运行动cortex-a8编译的内核?不让!).如果编译了多种处理器支持,如versatile 板,则会循环每种type依次查验,如果硬件读出的ID在内核中找不到匹配,则r5置0前往1:ldmiar5, {r3, r4}@ value, maskandr4, r4, r9@ mask wanted bitsteqr3, r4beq2faddr5, r5, #PROC_INFO_SZ@ sizeof(proc_info_list)cmpr5, r6blo1bmovr5, #0@ unknown processor2:movpc, lr__lookup_machine_type在文件的197行,编码办法与查抄processor ID完全一样,请参考前段__lookup_machine_type:adrr3, 3bldmiar3, {r4, r5, r6}subr3, r3, r4@ get offset between virt&physaddr5, r5, r3@ convert virt addresses toaddr6, r6, r3@ physical address space1:ldrr3, [r5, #MACHINFO_TYPE]@ get machine typeteqr3, r1@ matches loader number?beq2f@ foundaddr5, r5, #SIZEOF_MACHINE_DESC@ next machine_descblo1bmovr5, #0@ unknown machine2:movpc, lr代码回到head.S第92行,查抄atags正当性,然后创建初始页表bl__vet_atagsbl__create_page_tables创建页表的代码在218行,首先将内核起始地址-0x4000到内核起始地址之间的16K存储器清0__create_page_tables:pgtblr4@ page table address/** Clear the 16K level 1 swapper page table*/movr0, r4movr3, #0addr6, r0, #0x40001:strr3, [r0], #4strr3, [r0], #4strr3, [r0], #4strr3, [r0], #4bne1b然后在234即将proc_info中的mmu_flags加载到r7ldrr7, [r10, #PROCINFO_MM_MMUFLAGS] @ mm_mmuflags在242即将PC指针右移20位,得到内核第一个1MB空间的段地址存入r6,在s3c2410平台该值是0x300.接着按照此值存入映射标识movr6, pc, lsr #20@ start of kernel sectionorrr3, r7, r6, lsl #20@ flags + kernel basestrr3, [r4, r6, lsl #2]@ identity mapping完成页表设置后回到102行,为打开虚拟地址映射作准备.设置sp指针,函数前往地址lr指向__enable_mmu,并跳转到linux-2.6.24-moko-linuxbj/arch/arm/mm/proc-arm920.S的386行,清除I-cache、D-cache、write buffer 和TLB__arm920_setup:movr0, #0mcrp15, 0, r0, c7, c7@ invalidate I,D caches on v4mcrp15, 0, r0, c7, c10, 4@ drain write buffer on v4#ifdef CONFIG_MMUmcrp15, 0, r0, c8, c7@ invalidate I,D TLBs on v4#endif然后前往head.S的158行,加载domain和页表,跳转到__turn_mmu_on__enable_mmu:#ifdef CONFIG_ALIGNMENT_TRAPorrr0, r0, #CR_A#elsebicr0, r0, #CR_A#endif#ifdef CONFIG_CPU_DCACHE_DISABLEbicr0, r0, #CR_C#endif#ifdef CONFIG_CPU_BPREDICT_DISABLEbicr0, r0, #CR_Z#endif#ifdef CONFIG_CPU_ICACHE_DISABLEbicr0, r0, #CR_I#endifmovr5, #(domain_val(DOMAIN_USER, DOMAIN_MANAGER) | \domain_val(DOMAIN_KERNEL,DOMAIN_MANAGER) | \domain_val(DOMAIN_TABLE, DOMAIN_MANAGER) | \domain_val(DOMAIN_IO, DOMAIN_CLIENT))mcrp15, 0, r5, c3, c0, 0@ load domain access registermcrp15, 0, r4, c2, c0, 0@ load page table pointerb__turn_mmu_on在194行把mmu使能位写入mmu,激活虚拟地址.然后将原来保管在sp中的地址载入pc,跳转到head-common.S的__mmap_switched,至此代码进入虚拟地址的世界movr0, r0mcrp15, 0, r0, c1, c0, 0@ write control regmrcp15, 0, r3, c0, c0, 0@ read id regmovr3, r3movr3, r3movpc, r13在的37行开始清除内核bss段,processor ID保管在r9,machine ID报存在r1,atags地址保管在r2,并将控制存放器保管到r7定义的内存地址.接下来跳入linux-2.6.24-moko-linuxbj/init/main.c的507行,start_kernel函数.这里只粘贴部分代码(第一个C语言函数,作一系列的初始化)__mmap_switched:adrr3, __switch_data + 4ldmiar3!, {r4, r5, r6, r7}cmpr4, r5@ Copy data segment if needed1:cmpner5, r6ldrnefp, [r4], #4strnefp, [r5], #4bne1basmlinkage void __init start_kernel(void){char * command_line;extern struct kernel_param __start___param[], __stop___param[];smp_setup_processor_id();/** Need to run as early as possible, to initialize the* lockdep hash:*/lockdep_init();debug_objects_early_init();cgroup_init_early();local_irq_disable();early_boot_irqs_off();early_init_irq_lock_class();/** Interrupts are still disabled. Do necessary setups, then* enable them*/lock_kernel();tick_init();boot_cpu_init();page_address_init();printk(KERN_NOTICE);printk(linux_banner);setup_arch(&command_line);mm_init_owner(&init_mm, &init_task);setup_command_line(command_line);setup_per_cpu_areas();setup_nr_cpu_ids();smp_prepare_boot_cpu();/* arch-specific boot-cpu hooks */ /** Set up the scheduler prior starting any interrupts (such as the* timer interrupt). Full topology setup happens at smp_init() * time - but meanwhile we still have a functioning scheduler. */sched_init();/** Disable preemption - early bootup scheduling is extremely * fragile until we cpu_idle() for the first time.*/preempt_disable();build_all_zonelists();page_alloc_init();printk(KERN_NOTICE "Kernel command line: %s\n", boot_command_line);parse_early_param();parse_args("Booting kernel", static_command_line, __start___param,__stop___param - __start___param,&unknown_bootoption);if (!irqs_disabled()) {printk(KERN_WARNING "start_kernel(): bug: interrupts were ""enabled *very* early, fixing it\n");local_irq_disable();}sort_main_extable();trap_init();rcu_init();/* init some links before init_ISA_irqs() */early_irq_init();init_IRQ();pidhash_init();init_timers();hrtimers_init();softirq_init();timekeeping_init();time_init();sched_clock_init();profile_init();if (!irqs_disabled())printk(KERN_CRIT "start_kernel(): bug: interrupts were " "enabled early\n");early_boot_irqs_on();local_irq_enable();/** HACK ALERT! This is early. We're enabling the console before* we've done PCI setups etc, and console_init() must be aware of* this. But we do want output early, in case something goes wrong.*/console_init();if (panic_later)panic(panic_later, panic_param);lockdep_info();/** Need to run this when irqs are enabled, because it wants* to self-test [hard/soft]-irqs on/off lock inversion bugs* too:*/locking_selftest();#ifdef CONFIG_BLK_DEV_INITRDif (initrd_start && !initrd_below_start_ok &&page_to_pfn(virt_to_page((void *)initrd_start)) < min_low_pfn) {printk(KERN_CRIT "initrd overwritten (0x%08lx < 0x%08lx) - ""disabling it.\n",page_to_pfn(virt_to_page((void *)initrd_start)),min_low_pfn);initrd_start = 0;}#endifvmalloc_init();vfs_caches_init_early(); cpuset_init_early();page_cgroup_init();mem_init();enable_debug_pagealloc(); cpu_hotplug_init();kmem_cache_init(); debug_objects_mem_init(); idr_init_cache();setup_per_cpu_pageset(); numa_policy_init();if (late_time_init)late_time_init();calibrate_delay();pidmap_init();pgtable_cache_init();prio_tree_init();anon_vma_init();#ifdef CONFIG_X86if (efi_enabled)efi_enter_virtual_mode();#endifthread_info_cache_init();cred_init();fork_init(num_physpages);proc_caches_init();buffer_init();key_init();security_init();vfs_caches_init(num_physpages);radix_tree_init();signals_init();/* rootfs populating might need page-writeback */ page_writeback_init();#ifdef CONFIG_PROC_FSproc_root_init();#endifcgroup_init();cpuset_init();taskstats_init_early();delayacct_init();check_bugs();acpi_early_init(); /* before LAPIC and SMP init */ftrace_init();/* Do the rest non-__init'ed, we're now alive */rest_init();}tatic noinline void __init_refok rest_init(void)__releases(kernel_lock){int pid;kernel_thread(kernel_init, NULL, CLONE_FS | CLONE_SIGHAND);numa_default_policy();pid = kernel_thread(kthreadd, NULL, CLONE_FS | CLONE_FILES);kthreadd_task = find_task_by_pid_ns(pid, &init_pid_ns); unlock_kernel();/** The boot idle thread must execute schedule()* at least once to get things moving:*/init_idle_bootup_task(current);rcu_scheduler_starting();preempt_enable_no_resched();schedule();preempt_disable();/* Call into cpu_idle with preempt disabled */cpu_idle();}static noinline int init_post(void){/* need to finish all async __init code before freeing the memory */async_synchronize_full();free_initmem();unlock_kernel();mark_rodata_ro();system_state = SYSTEM_RUNNING;numa_default_policy();if (sys_open((const char __user *) "/dev/console", O_RDWR, 0) < 0)printk(KERN_WARNING "Warning: unable to open an initial console.\n");(void) sys_dup(0);(void) sys_dup(0);current->signal->flags |= SIGNAL_UNKILLABLE;if (ramdisk_execute_command) {run_init_process(ramdisk_execute_command);printk(KERN_WARNING "Failed to execute %s\n", ramdisk_execute_command);}/** We try each of these until one succeeds.** The Bourne shell can be used instead of init if we are* trying to recover a really broken machine.*/if (execute_command) {run_init_process(execute_command);printk(KERN_WARNING "Failed to execute %s. Attempting ""defaults...\n", execute_command);}run_init_process("/sbin/init"); 根文件系统命令run_init_process("/etc/init");run_init_process("/bin/init");run_init_process("/bin/sh");panic("No init found. Try passing init= option to kernel."); }。

嵌入式系统中Linux2.6内核的应用

嵌入式系统中Linux2.6内核的应用
【 摘
许昌
4 10 ) 6 0 0
要】 在分析 Ln x . iu26内核新特性的基 础上, ¥ C 4 0开发板上移植 了 26内核和新 的文件 系统, 在 3 21 . 并成功地对 H.6 24编解码 多媒体 系
统提 供 了 支持 。
【 关键词】iu Ln x内核; 嵌入 式系统 ¥C2 1 3 40
随 着 多 媒 体 技 术 与 通 讯 技 术 相 结 合 的 信 息 技 术 的 快 速 发 展 和 互 ( 个 内 核 线 程 对 应 一 个 用 户 线 程 ) 一 ,包 括 内 核 对 新 的 N T (aie PLNt v 联 网的 广 泛应 用 ,c 时 代 也 过 渡 到 了后 P P c时 代 。 嵌 入 式 技 术 越 来 越 P SX T ra igLbay的 支 持 , 是 对 以 前 内 核 线 程 方 法 的 明 显 改 O I hedn irr1 这 与 人 们 的生 活 紧密 结 合 。 进 。 26 内 核 同 时 还 提 供 P SX s nl . O I i as和 P SX h小 一eouin g O I i rslt o Ln x操 作 系 统 是 一种 性 能 优 良 、源码 公 开 且 被 广 泛 应 用 的 免 费 t r。P SXsgas 会 丢 失, 且 可 以携 带 线 程 间或 处 理 器 间 的通 iu i s O I n l不 me i 并 操作系统, 由于 其 体积 小 、 裁 减 、 行 速 度 高 、 可 运 良好 的 网 络 性 能 等 优 信 信 息 。嵌 入 式 系统 要 求 系统 按时 间表 执 行 任 务 .O I ie 可 以 提 P SX t r m 点 , 以作 为 嵌 入 式 操作 系统 。 可 供 1Hz 触 发 器使 这一 切 变 得 简 单, 而可 以有 效 地 控 制进 度 。 k 的 从 Ln x的低 成 本 和 开 放 性 ,为 其 在 嵌 入 式 系 统 领 域 的应 用 营造 了 iu 1 . 控 制 器 的 支 持 Ln x. 核 加 入 了 多 种 微 控 制 器 的 支 5微 iu26内 肥 沃 的 土壤 。本 文 着 重 介 绍 Ln x26内 核 的新 特性 及 其 嵌 入式 应 用 持 。而 且 已经 将 其 整 合 进 了 新 的 内核 中, 始 支 持 多种 流 行 的无 MMU iu . 开 中 的优 势 , 将其 移植 到 嵌 入 式 平 台 中, 功 支 持 H2 4编 解 码 多 媒 体 微控 制 器 , 旧支 持 多 任务 处 理 , 没 有 内 存 保 护 功 能 。 同 时也 加 入 了 并 成 .6 仍 但 系统 。 许 多 流 行 的控 制 器 的 支持 , ¥ C 4 0等 。 如 32 1

了解Linux系统内核和驱动程序开发

了解Linux系统内核和驱动程序开发

了解Linux系统内核和驱动程序开发Linux系统内核是OS的核心组成部分,它连接了硬件和软件,允许软件与硬件交互。

内核需要有一个能够控制硬件的驱动程序。

在本文中,我们将介绍Linux系统内核和驱动程序开发的一些基本概念,以及如何了解和学习这些概念。

Linux系统内核是一个高度定制的操作系统内核,它可以定制化来适应不同的需求。

但是,无论哪种形式的Linux内核,它都负责处理硬件和为用户空间程序提供服务。

内核需要有针对每个硬件设备的设备驱动程序,以便内核和设备之间通信。

驱动程序开发是将新硬件添加到系统时必不可少的一部分。

开发驱动程序需要对内核响应机制的了解,以及对硬件的了解。

设备驱动程序应该提供一些API,可以由需要使用设备的软件来调用这些API。

了解内核认识一个软件产品的最好方法是阅读其源文件或代码。

在Linux中,内核的源代码是免费的,并且是公开的。

这为在深入了解内核的运作方式以及设计器提供了机会。

内核可在内核文件系统中找到,其中包括全部的源文件。

学习内核在学习内核时,第一步是学习操作系统概念。

有很多优秀的操作系统课程,可用于学习操作系统基本原理。

其次,学习一些基本的数据结构和算法,如链表、栈和队列。

然后,可以学习操作系统接口和内核概念。

这些可在内核源代码中找到。

了解内核APILinux内核暴露出一些API,允许编写驱动程序,这些API包括字符设备、块设备、网络设备等。

Linux设备驱动程序还应该提供一些常规操作设备的API,例如读写、打开和关闭。

这些API 可在内核中找到,也可以找到它们的文档。

了解驱动程序开发Linux内核设备驱动程序需要了解内核数据结构、API,以及所开发的设备硬件的特殊功能。

Linux内核驱动程序包括字符、块和网络驱动程序。

字符驱动程序传输ASCII数据,块驱动程序传输二进制数据,而网络驱动程序传输数据包。

Linux内核实现驱动程序的方式是通过系统调用。

在驱动程序开发之前,需要了解每个硬件设备的功能,以确保正确地实现设备函数。

嵌入式Linux2_6内核的CAN驱动设计与实现

嵌入式Linux2_6内核的CAN驱动设计与实现

33962010,31(15)计算机工程与设计Computer Engineering and Design0引言在嵌入式领域中,Linux2.6内核除了提高其实时性能,系统地移植更加方便,同时添加了新的体系结构和处理类型,可以支持大容量内存模型、微控制器,同时,还自带了很多总线驱动程序,虽然Linux 并非一个真正的实时操作系统,但2.6内核的改进能够满足大部分的应用需求,所以Linux2.6内核将会在嵌入式系统领域中大展身手[1]。

CAN (controller area network )是一种有效支持分布式控制或实时控制的串行通信网络,CAN 协议的最大特点是数据块的标识码可由11位或29位二进制数组成,可定义211或219个不同的数据块,使得CAN 总线构成的网络节点的数据通信实时性更强,提高了系统的可靠性和灵活性[2]。

传统的嵌入式系统CAN 总线驱动设计是基于嵌入式Linux2.4内核,本文着重研究和实现了在嵌入式Linux2.6内核的S3C2410开发板上使用Linux2.6自带的SPI 驱动实现CAN 总线的开发,并详细分析了在嵌入式Linux2.6.24内核下加载和声明SPI 总线的具体步骤,CAN 总线驱动初始化和中断控制的设计方法,以及CAN 驱动加载步骤。

1系统硬件设计系统硬件设计主要由微处理器S3C2410、带SPI 接口的独立CAN 控制器MCP2510与高速CAN 收发器TJA1050等器件组成[3]。

1.1芯片介绍(1)S3C2410:S3C2410是一款为手持设备和一般类型应用提供的一款高性能、低功耗、低价格微处理器。

内部采用高级微控制总线(AMBA )体系结构,主频高达203MHz ,集成3通道UART ,4通道DMA ,2通道的SPI [4]。

(2)MCP2510:MCP2510完全支持CAN 总线V2.0A/B 技术规范,能够发送和接收标准和扩展报文,同时具备验收过滤以及报文管理功能。

一文详解Linux线程同步

一文详解Linux线程同步

一文详解Linux线程同步简介:程磊,一线码农,在某手机公司担任系统开发工程师;阅码场荣誉总编辑;日常喜欢研究内核基本原理。

目录:一、概念解析1.1 名词解释1.2 线程同步与防同步二、线程防同步方法2.1 时间上防同步2.2 空间上防同步2.3 事后防同步三、原子操作3.1 int原子操作3.2 long原子操作3.3 bit原子操作四、加锁机制4.1 锁的底层原理4.2 简单自旋锁4.3 互斥锁4.4 信号量五、per-CPU变量六、RCU 简介七、序列锁八、总结回顾一、概念解析我们在工作中会经常遇到线程同步,那么到底什么是线程同步呢,线程同步的本质是什么,线程同步的方法又有哪些,为什么会有这些方法呢?在回答这些问题之前,我们先做几个名词解释,以便建立共同的概念基础。

1.1 名词解释CPU:本文中的CPU都是指逻辑CPU。

UP:单处理器(单CPU)。

SMP:对称多处理器(多CPU)。

线程、执行流:线程的本质是一个执行流,但执行流不仅仅有线程,还有ISR、sof ti rq、tasklet,都是执行流。

本文中说到线程一般是泛指各种执行流,除非是在需要区分不同执行流时,线程才特指狭义的线程。

并发、并行:并发是指线程在宏观上表现为同时执行,微观上可能是同时执行也可能是交错执行,并行是指线程在宏观上是同时执行,微观上也是同时执行。

伪并发、真并发:伪并发就是微观上是交错执行的并发,真并发就是并行。

UP上只有伪并发,SMP上既有伪并发也有真并发。

临界区:访问相同数据的代码段,如果可能会在多个线程中并发执行,就叫做临界区,临界区可以是一个代码段被多个线程并发执行,也可以是多个不同的代码段被多个线程并发执行。

同步:首先线程同步的同步和同步异步的同步,不是一个意思。

线程同步的同步,本文按照字面意思进行解释,同步就是统一步调、同时执行的意思。

线程同步现象:线程并发过程中如果存在临界区并发执行的情况,就叫做线程同步现象。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
当系统功能越来越多 ,使用操作系统就很有必要 。L inux 是开放源码的操作系统 ,因其具有高可靠性 、资源丰富 、免费 等优点 ,使得它在嵌入式领域越来越流行 [4 ] 。正是由于 L inux
开放源代码 ,使得众多的软件设计者不断为其更新和优化 。 至今为止 , L inux内核已经发展到 2. 6版本 ,与 L inux2. 4 内核 相比 ,它在性能 、安全性和设备模型等方面都作了极大的改 进 。而随着 L inux内核版本的升级 ,驱动程序的开发也要作 相应的修改 [ 5 - 6 ] 。
首先通过 resource元素定义 SSC0的设备资源信息 。 ssc0 _resources[ 0 ]定义了 AT91RM9200 SSC0 外设映射到地址空 间的范围 ,从 AT91RM9200 _BASE_SSC0 ( 0xFFFD0000)开始 , 长度为 16 KB。 ssc0 _ resources [ 1 ]定义了 SSC0 设备的中断
1 AT91RM9200同步串行控制器 SSC接口分析
AT91RM9200是一款高性能 、低功耗和低成本的嵌入式 ARM 微处理器 ,内部集成了丰富的系统资源和外设接口 ,被 广泛应用于各种工业控制系统中 。它提供了 3个同步串口控
收稿日期 : 2009 - 09 - 21;修回日期 : 2009 - 11 - 13。 作者简介 :仇洁婷 (1985 - ) ,女 (壮族 ) ,广西钦州人 ,硕士研究生 ,主要研究方向 :物探仪器 ; 陈儒军 ( 1973 - ) ,男 (土家族 ) ,贵州思南人 , 副教授 ,博士 ,主要研究方向 :物探仪器 ; 何展翔 (1962 - ) ,男 ,湖南平江人 ,教授级高级工程师 ,主要研究方向 :综合物化探采集处理解释方法 。
图 1 SSC设备驱动的程序结构 2. 1 SSC驱动的 Platform 注册
L inux2. 6. 21 内 核 把 AT91RM9200 处 理 器 内 部 集 成 的 I2 C、SP I和看门狗等都归纳为平台设备 ,并由内核统一管理 。 平台设备用 p latform _device结构体来描述 ,包含其所用的资 源数量和指针 。 SSC作为 AT91RM9200处理器内部集成的外 设接口 ,需要通过 p latform _device进行注册 。AT91RM9200的 p latform 平 台 设 备 注 册 在 / arch / arm /mach2at91 / at91 rm9200 _ device. c文件中执行 。
第 30卷第 3期 2010年 3月
计算机应用 Journal of Computer App lications
Vol. 30 No. 3 M ar. 2010
文章编号 : 1001 - 9081 (2010) 03 - 0850 - 04
L inux216内核下同步ct: The communication between ARM and D igital Signal Processor (DSP) is a key factor in ARM /DSP dual core design w idely used in geophysics exp loration instrumentation. In this paper serial synchronous communication between AT91RM9200 /DSP56309 dual core p rocessors was realized and the modularized and hierarchical design of the SSC driver based on AT91TM9200 in L inux 2. 6 was introduced in detail. The DMA transm ission, multi2buffering and PDA controller p riority modification was used in the driving design. The SSC interface circuit imp lementation based on the design was also introduced. The experimental results show that the data transfer between AT91RM9200 /DSP56309 is rap id and steady, and so that the dual core p rocessors co2work very well.
Q IU J ie2ting1, 4 , CHEN Ru2jun1, 2, 3 , HE Zhan2xiang4 , Q IU Kai2lin4
(1. School of Info2physics and Geom atics Eng ineering, Cen tral S outh U n iversity, Changsha Hunan 410083, China; 2. Postdoctora l S tation of Com pu ter S cience and Technology, Cen tral S outh U n iversity, Changsha Hunan 410083, China; 3. Postdoctoral R esea rch S ta tion of B ureau of Geophysica l P rospecting, Ch ina N ationa l Petroleum Corpora tion, Z huozhou Hebei 072751, Ch ina;
Key words: serial synchronous communication; AT91RM9200; DSP56309; L inux2. 6
0 引言
随着地球物理勘探仪器在功耗 、性能和成本等方面要求 越来越高 ,嵌入式 ARM 处理器在地球物理勘探仪器领域的 应用也不 断 扩 大 [1 ] 。同 时 , 由 于 数 字 信 号 处 理 器 ( D igital Signal Processor, DSP) 在 数 字 滤 波 、快 速 傅 里 叶 变 换 ( Fast Fourier Transformation, FFT)和谱分析等方面具有明显的优越 性 ,使得它被广泛用于高精度数据运算和复杂数据处理的地 球勘探仪器中 [2 ] 。但是 DSP没有功能强大的操作系统 ,不适 合做系统控制 ,而这正好是 ARM 的强项 。由此可见 ,通过采 用 ARM 与 DSP的结合可充分发挥二者的优势 [3 ] ,从而提升 仪器的性能 。然而 ,这种 ARM /DSP双核处理器系统的关键 技术是如何实现双核之间的通信 ,以确保系统能够对信号进 行实时 、高效的传输和处理 。
4. Postg raduate R esea rch S ta tion of N on2seism ic S u rvey, B ureau of Geophysica l P rospecting, China N a tiona l Petroleum Corpora tion, Zhuozhou Hebei 072751, Ch ina)
摘 要 :随着 ARM /DSP双核处理器在地球物理勘探仪器中的推广应用 ,双核间的通信成为实现这种双核处理器 系统的关键技术 。针对 L inux2. 6版本内核 ,详细介绍了基于 AT91TM9200 的 SSC同步串行通信设备驱动的模块化 、 分层次的设计架构 ,并在驱动中使用 DMA 传输模式 、分段缓存技术和修改 PDA 控制器优先级 。在此基础上给出了 AT91RM9200 /DSP56309双核的接口电路设计 。试验表明 ,在 AT91RM9200 /DSP56309双核中利用同步串行同步通信 的设计 ,能够使系统高效 、稳定 、快速地进行数据传输 ,从而使双核处理器能够很好地协同工作 。
针对上述分析 ,本文基于 ATM EL 公司 AT91RM9200 的 同步串行控制器 ( Serial Synchronous Controller, SSC) ,着重讨 论在 L inux2. 6. 21内核下如何开发和设计 SSC驱动程序 。最 后 ,以 DSP56309芯片作为数字信号处理器 ,以 AT91RM9200 芯片作为微控制器 ,采用 SSC作为 ARM 和 DSP之间的通信 接口 ,对 L inux2. 6. 21内核下的 SSC驱动程序进行测试和分 析。
2 L inux2. 6内核下 SSC驱动整体结构
L inux2. 6. 21内核源码没有提供 SSC接口的设备驱动程 序 ,本文针对于 AT91RM9200芯片的 SSC外设接口重新构建 SSC设备驱动 。 SSC驱动是字符设备驱动程序 ,它主要完成 以下工作 :
1)设计 SSC平台设备的注册函数 ; 2)设计 SSC的模块加载函数和卸载函数 ; 3)设计 SSC的 DMA传输模式和 read读函数 。 可将 SSC驱动程序分为 3 个层次 (如图 1 所示 ) 。最底 层由 at91 rm9200 _device. c文件获取了 SSC设备总线地址和 中断号 ,以及使能 SSC接口管脚 。 board2dk. c文件在 L inux系 统启动时注册了 SSC设备 ,以便上层 SSC设备驱动程序获取 SSC的硬件资源 。 at91_ssc. c文件实现了 SSC设备和 DMA 控 制器的初始化 、设备号和中断号的注册 、注销以及提供了用户 空间的 file_operations操作 (包括 open、read、ioctl和 close函数 操作 ) 。由于 AT91RM9200的 3个 SSC外围接口接收器 /发生 器用法类似 ,本文就仅介绍 SSC0接收器驱动程序设计 。
关键词 :同步串行通信 ; AT91RM9200; DSP56309; L inux2. 6 中图分类号 : TP316 文献标志码 : A
相关文档
最新文档