You are on page 1of 3

DOI:10.16208/j.issn1000-7024.2008.23.

009

第 29 卷 第 23 期 计算机工程与设计 2008 年 12 月
Vol. 29 No. 23 Computer Engineering and Design Dec. 2008

嵌入式 Linux下基于 SPI总线的网络设备驱动设计与实现


张晓雷 1, 陈相宁 1, 郭 剑2
(1. 南京大学 网络安全通信实验室,江苏 南京 210093;
2. 瑞博强芯 ( 天津 ) 科技有限公司 南京研发中心,江苏 南京 210093)
摘 要 :基 于 SPI 总 线的 网络 驱 动设 备是 一种 新 型的 网络 设备 ,其 驱动 程 序设 计尚 未经 过 系统 分析 。 在分 析嵌 入式 Linux 的
SPI 总线 特 点的 基础 上,以 S3C2410 为 MCU、以 ENC28J60 为 以 太网 控制 芯片 作 为设 计实 例,首次 详细 分 析介 绍了 基 于 SPI 总
线 的网 络驱 动 设计 的方 法。
关 键词 :
SPI 总线 ; 网络 设 备驱 动; 嵌 入式 Linux; ENC28J60
中 图法 分类 号 :TP316 文 献标 识码 :A 文 章编 号 :1000-7024 (2008) 23-6003-03

Design and implementation of embedded Linux network device driver based on SPI bus
ZHANG Xiao-lei1, CHEN Xiang-ning1, GUO Jian2
(1. Safe Communication Research Lab, Nanjing University, Nanjing 210093, China;
2. Nanjing Research Center, Rainbow Qiangxin (Tianjin) Technologies Corporation, Nanjing 210093, China )

Abstract:The network device based on SPI bus is a new class of network device, however, the design of its driver isn’ t analyzed
generally. The embedded Linux network device driver architecture based on SPI is discussed originally and how to write a new network
device driver based on SPI for embedded Linux is explained.
Key words:SPI bus; network device driver; embedded Linux; ENC29J60

其它 事务。因此 ,开发基于 SPI 总 线的网络驱 动程序除了 要涉


0 引 言
及 Linux 内核网络 驱动程序的知识外,还要对这类 驱动程序体
SPI(serial peripheral interface,串行外设接口)总线系统是一 系结 构有深入 了解。
种同步串行外设接口,它可以使 MCU 与各种外围设备以串行 本文从工业实现的角度详细分析了在嵌入式 Linux 下基于
方式进行通信以交换信息。外围设置 FLASHRAM、网络控制 SPI 总线的网络驱动体系结构,以业界最新的 ENC28J60 以太网
器、LCD 显示驱动器、A/D 转换器和 MCU 等。SPI 总线系统可 控制芯片为设计实例进一步分析和实现了以 S3C2410 为 MCU
直接与各个厂家生产的多种标准外围器件直接接口,
该接口一 的嵌入式 Linux2.4 内核下的以太网驱动程序,最后给出总结。
般使用 4 条线:串行时钟线 (SCK)、主机输入/从机输出数据线
1 Linux 中基于 SPI 总线的网络驱动体系结构
MISO、主机输出/从机输入数据线 MOST 和低电平有效的从机
选择线 SS(有的 SPI 接口芯片带有中断信号线 INT 或 INT、有的 1.1 Linux 中 SPI 总 线的 构成
同目前广
SPI 接口芯片没有主机输出/从机输入数据线 MOSI)。 在介绍 SPI 总 线驱动体系 结构前,需 要对 SPI 总线驱 动作
泛采用的 PCI 总线相比,由于 SPI 系统总线一共只需 3~4 位数 一些 了解。利 用 SPI 总 线可在软 件的控制下 构成各种系 统。
据线和控制即可实现与具有 SPI 总线接口功能的各种 I/O 器件 如 1 个主 MCU 和几个从 MCU、几个 从 MCU 相互连接构 成多
进行接口,而扩展并行总线则需要 8 根数据线、8~16 位地址线、 主机 系统(分布 式系统)、1 个主 MCU 和 1 个或 几个从 I/O 设备
2~3 位控制线,因此,采用 SPI 总线接口可以简化电路设计,节 所构 成的各种 系统等。在 大多数应用 场合,可使 用 1 个 MCU
省很多常规电路中的接口器件和 I/O 口线,提高设计的可靠性。 作为 控机来控 制数据,并向 1 个 或几个从外 围器件传送 该数
我们在开 发基于 S3C2410 的嵌入 式 Linux 系统中 发现基 据。从器件只 有在主机 发命令时才 能接收或发 送数据。其数
于 SPI 的网 络设备相 关讨论非常 少,而其应 用前景却相 当好, 据的 传输格式 是高位 (MSB) 在 前,低位 (LSB) 在 后。Linux 中
例如 ,在 远程控制不 需要特别高 的通信速 率的背景下 采用基 SPI 总线接 口系统的典 型结构如图 1 所示。
于 SPI 总 线的网络 设备能够极 大的节省 CPU 端口线用 于处理 当一个主 控机通过 SPI 与 几种不同 的串行 I/O 芯片 相连

收稿日期:2007-12-02 E-mail:cnlunwen@163.com
作者简介:张晓雷 (1983-),男,河南信阳人,硕士研究生,研究方向为嵌入式操作系统和计算机通信; 陈相宁 (1967-),男,江苏镇江人,
博士,副教授,研究方向为无线通信网、接入网技术、网络信息安全及信息论、信息处理; 郭剑 (1978-),男,湖南永州人,硕士,研究方向
为嵌入式操作系统和数据通信。

- 6003 -
SCK
计;②通用网络驱动程序接口的设计;③网络芯片的控制设计。
主控制 MCU MOSI SPI 总线 驱动位于 网络驱动的 最底层,直 接控制芯 片与
MISO MCU 的数据 包和控制命 令等的交互 ,它不考虑 传输数据 的具
被控制器 1 被控制器 2 被控制器 n 体含 义,只是 每次简单的 接收或发 送 8 比特数据 (或称为 一个
SS1 SS2 SSn
octet)。这一部分 设计的好坏 直接关系 驱动体系是 否可用。
通用网络 驱动接口的 设计的主 要工作为驱 动设备的 net_
图1 SPI 总线的构成 device 结构的初始化与注册,该结构由嵌入式 Linux 内核定义。
其中 初始化过程 将 1、3 步骤针对 网络芯片量 身定做的驱 动函
时,必须使用每 片的允许控 制端,这可通 过 MCU 的 I/O 端 口输
数映 射到 net_device 结构中,并作为接 口函数提供 给系统,这
出 线来实现。 但应特别注 意这些串行 I/O 芯片 的输入输 出特
些接 口包括 open()、stop()、hard_start_xmit()以及请求中断 函数,
性 :首先是 输入芯片的 串行数据输 出是否有三 态控制端 。平
注册 仅仅是通 过调用系统 提供的 register_netdev () 函数将 已初
时 未选中芯片 时,输出端 应处于高阻 态。若没 有三态控制 端,
始化 的设备告 知系统。
则 应外加三态 门。否则 MCU 的 MISO 端只能 连接 1 个输 入芯
网络芯片 的控制主要 根据芯片 的 datasheet 为驱动函 数量
片 。其次是输 出芯片的串 行数据输 入是否有允 许控制端。因
身定 做,并通过 调用 SPI 驱动接口在 网络芯片与 MCU 之 间传
此只有 在此芯片允许时,SCK 脉冲才把串行数据移入 该芯片;
递控 制命令与 数据包。
在 禁止时,SCK 对芯片 无影响。若没 有允许控 制端,则应 在外
围用门电路对 SCK 进行控制,然后再加到芯片的时钟输入端; 2 实 例
当 然,也可以只 在 SPI 总线上连 接 1 个芯片 ,而 不再连接 其它
S3C2410 包含两个 SPI 总 线接口,每 个都单独拥 有 8bit 的
输 入或输出芯 片。
移位 寄存器用 于传输和接 收数据,我们在工程 中采用新 型的
1.2 Linux 中 基于 SPI 总 线的 网络驱 动体 系结 构
采用 SPI 接口的 ENC28J60 以太网 控制芯片作 为外部网 络芯
Linux 内 核基于 SPI 总线的 网络驱动体 系结构如 图 2 所
片 用于 对系 统 进行 控制 。ENC28J60 是全 球目 前 最小 封装 的
示 ,驱动工作 模式的设 计包括 3 个方 面:①SPI 总线驱动 的设
以太网控制器,在此之前,嵌入式设 计人员在为远程控制或监
dev_queue_xmit () netif_rx () 控提供应 用接入时可选的以太网控制器都是专为 个人计算系
上层下传数据 sk_buff 向上层传输数据
统设 计的,既复杂、又占空间 ,且比 较昂贵。目 前市场上 大部
网络设备驱动接口 分以太网控制器采用的封装均超过 80 引脚,而符合 IEEE 802.3
协议 的 ENC28J60 只有 28 引脚 ,就能既提供 相应的功能,又可

初始化网络驱动 hard_start_xmit () interrupt () 中断例程,


以大 大简化相 关设计。其 详细信息参 见 datasheet[]。
与 SPI 接口 向 SPI 总线发送数据 从 SPI 总线接收数据
S3C2410 提供了下 面两组共 4 对寄存器来 控制 SPI 总 线:
nSSn:片选使能控制寄存器;SCKn:时钟控制器;SPIMOSIn:数
SPI 驱动接口
据输 出寄存器 ;SPIMISOn:数据输入 寄存器。它 与 ENC28J60
的连 接如图 3 所示,ENC28J60 的片选信 号线 CS 接 S3C2410 的
SPI 总线
nSSn,时钟线 SCK 接 SPICLKn,输入信号线 SI 接 SPIMOSIn,
图2 Linux 内核基于 SPI 总线的网络驱动体系结构 输出 信号线 SO 接 SPIMISOn。所 有控制 ENC28J60 的操 作都

3.3V RJ-45
TPOUT+ 50 Ferrite 1
I/O CS 1% Bead( 1)
SCK SCK 2
50 0.01 F
SDO SI
1% 1: 1 CT 3
SDI SO TPOUT-
TPIN+ 4
MCU 5.0V←3.3V ENC28J60 50
Level 1%
Shift 0.01 F 5
50
Logic (2) 1% 1: 1
TPIN- 6
INT0 INT
INT1 WOL 7
VCAP LEDA LEDB RBIAS 8
2K
1% . 001 F
10 F
2kV

Note 1: Ferrite Bead should be rated for at least 100 mA.


2: Required only if the microcontroller is operating at 5V.

图3 S3C2410 与 ENC28J60 接口电路

- 6004 -
要 通过读写 其中被 选取使 用的一组 寄存器 来完成。另外,
系统配置调用 dev_queue_xmit (), netif_rx ()
S3C2410 还 提供了一对 SPI 总线 中断信号线 EINTn,我们 使用
的 是 EINT1,申请的中断 号为 1。所 有上述寄存 器都必须 通过 ENC28J60
PhyWrite (), PhyRead () Xmit (), Interrupt () 驱动接口
GPI/O 控制 寄存器单独 设定。
下面将在 嵌入式 Linux 2.4 内核和 S3C2410 开发系统 中实
现 基于 SPI 总线的 ENC28J60 的网 络驱动程序 。同上文 介绍 Write (), Read ()

的 一般方法相 一致,分为了 3 个 方面,即如何初始 化基于 SPI


SetBank ()
的 网络驱动、如何设计网 络驱动接口 和如何设计 驱动构架 。
2.1 基 于 SPI 总线 的 ENC28J60 驱 动模 块初 始化例 程 SPI 驱动接口
WriteOp (), ReadOp () WriteBuffer (), ReadBuffer ()
该 例 程按 照 设 计 要 求 完 成相 应 的 初 始 化 工 作, 主 要 完
成 :①初始化 enc28j60 数据结 构,具体包括 get_stats/open/stop/ ChipSelect ()
hard_start_xmit 函数 映射,MAC 地 址初始化赋 值,以及 调用
ether_setup () 进行部分功 能默认初始 化、request_irq () 申 请中 __raw_writeb (), __raw_readb ()
断 ;②调用 register_netdev () 函数注 册已初始 化的驱动设 备;
图4 ENC28J60 驱动程序框架
③ 调用初始化 SPI 驱动的函 数----spi_init (),它主 要读写 GPIO
寄 存器,其流 程如下: 对于第 2 种 操作,根据 ENC28J60 的手册,不能直接 读写
(1)配置 GPG5,GPG6,GPG7 为 SPI1 接口 ,并将 GPG0 配置 MAC 地址 寄存器,必须 通过相应控 制寄存器 的读写来实 现;
为 输出 因此 定义了 PhyWrite (),PhyRead () 接口 函数,屏 蔽了这种 间接
(2)将 GPG0,GPG5,GPG6,GPG7 相应 bit 位置 1,取消挂起 调用 控制寄存 器读写函数 Read()、Write()的细 节。
(3)配置 GPF1 和 GPF4 为输入 (并将 GPF1 作为中断 I/O 口) 对于第 3 种 操作,即 Read ()、Write () 接口函 数简单的 对控
(4)取消 GPF1 和 GPF4 的 挂起 制寄 存器的配 置,主要 用于在系统 初始化时调 用和被前 两种
(5)配置 SPI prescaler 为 10M 的波 特率 操作 机制间接 调用。值得 注意的是 因为 ENC28J60 控制 寄存
(6)配置 SPI 为 master 模式,并打开 器本 身分为 4 个 池,在 选取某一个 寄存器的时 候需要用 所有
2.2 SPI 驱 动接 口函 数 池共 享的 ECON1 控制寄存 器在不同池之 间进行切换,因 此设
读写函数分为两部分,ENC28J60 控制寄存器的读写 Write- 计了 专用的函 数 SetBank()。
Op()、ReadOp()和缓冲区数据的读写 WriteBuffer()、ReadBuffer()。
3 结束语
第 一组函数的 主要工作是 将 3bit 的 操作数和 5bit 的地址 组合
为 8bit 的数据单元 在 SPI 总线上传 递。第二组 函数的主 要工 SPI 总 线是一种 MCU 与外设通 信的通用 总线,基于 SPI
作 是 将指 定 长 度的 数 据通 过 SPI 总线 按 字节 大 小 分批 写 入 总线 的网络接 口设备是一 种新型的网 络设备,其较简单 的实
ENC28J60 的 缓冲区。注 意:①需要 在每次读写 前使能 CS,在 现方 案和体系 构架使得其 在远程配置 、调试等 方面有着 广泛
结束 后取消 CS; ②需 要在每次读写后 udelay(1),确保操 作有时 的用 途,而这 方面的相 关设计方法 却很少。本 文首次详 细分
间 完成。具体的读 写时序参 见 ENC28J60 的 datasheet。我 们给 析和 设计了在 嵌入式 Linux 系统平台 下基于 SPI 总线的 驱动
出 这两组函数 的声明用作 对比: 设备的 设计和实现方法,并以最新的 ENC28J60 芯片为 例详细
u8 enc28j60ReadOp(u8 op, u8 address); 给出 了其驱动 程序的构建 方法,类 似的方法同 样适用于 其它
void enc28j60WriteOp(u8 op, u8 address, u8 data); 网络 设备芯片 甚至拓展到 其它非网络 设备,同 时向业界 介绍
void enc28j60_ReadBuffer(u16 len, u8 *data); 了一 种能够广 泛用于业务 通信和远程 控制的网 络设备,拓展
void enc28j60_WriteBuffer(u16 len, u8 *data ); 了人 们所关注 的网络设备 的视角。
2.3 基 于 SPI 总线 的 ENC28J60 驱 动模 块构 架
参考文献:
在这里给出驱动程序 的框架和功能,如图 4 所示 ,驱动程
序主要实现 3 种操作:①用 Xmit()和 interrupt()接口函数传输和 [1] Christian Benvenuti.Understanding Linux networking internals
中断方式接收 数据包;②用 PhyWrite()和 PhyRead()接口函数写 [M].O'Reilly & Associates,2006.
和 读取设备 MAC 地址;③用 Write () 和 Read () 函数直 接对 [2] Greg Kroah-Hartman.Linux 设备驱动程序[M]. 魏永明,译. 北
ENC28J60 的 控制寄存器 进行读写 。 京:中国电力出版社,2006.
对于第 1 种操作,Xmit()和 Interrupt()函数首先通过间接调 [3] ENC28J60 Stand-Alone ethernet controller with SPI product
Read()以 太网接口函 数通过 SPI 总线通知 ENC28J60
用 Write()、 brief[S].Microchip Technology Inc,2004.
设备,将其设为数据发送和 接收状态,然后根据寄存器数据包 [4] S3C2410X 32-Bit RISC micro processor user's manuaL[S].
的 长度调用 SPI 驱 动接口函 数 WriteBuffer()、ReadBuffer () 函数 [5] 全成斌, 任秀丽, 范力军, 等.嵌入式系统以太网驱动程序的设
将 数据写入/读 出设备缓 冲区,最后 再次调用 Write()、Read()函 计方法[J].小型微型计算机系统,2002,23(9):1029-1032.
数 将相应缓冲 区的指针移 至下一个空 分组区,并通知系 统发 [6] 李祥兵,郑扣根.Linux 中 I2C 总线驱动程序的开发 [J].计算机
送 、接收下一 个数据包。 工程与设计,2005,26(1):41-43.

- 6005 -

You might also like