EDA365电子论坛网

标题: Linux驱动移植——ENC28J60以太网控制器 [打印本页]

作者: piday123    时间: 2020-5-27 16:17
标题: Linux驱动移植——ENC28J60以太网控制器
开发板:E9(飞思卡尔的imx6q主控)+ x6 r5 ]  F# G. F9 F: Z5 n

9 K) r; q/ @. V# Q9 a$ k内核:Linux 3.0.350 F% X9 P$ t% s+ D

3 x, {: \; }  j; j3 J7 _' s' IPC OS:Ubuntu 11.04( w# }' s* Q8 R3 H# l

6 b; {5 h1 q% K8 ~8 f. T
' U: r! |3 D# I- K2 S) w1 E% @/ |4 B+ z
本文对ENC28J60模块的驱动移植进行简单梳理。该模块购于淘宝。
9 h- O. y# ~  o
, O8 X$ z7 x- y按照一般移植要素,有如下几个步骤:
! q2 s9 h6 f, l  K: d3 x
! `8 h9 ?" @) S* G4 E2 D1. 按照各引脚所对应的功能进行初始化操作。
+ a; n3 p8 A$ f& \& v& o
! K- z2 C1 P3 ?4 S7 S( f7 s2. 确定总线类型,在bsp中注册相应的主控制器信息。  k& x: C  o6 H" P8 R: ^. }6 V

4 l" Z3 o" N# S; }3.在bsp中添加设备信息。5 @: p9 D* P! ?6 {# k( i5 u

3 c. U% ]- N+ P* A4. 配置内核,打开设备配置选项。; b  `  ~* e, G2 p& G
$ A$ e5 V- ~& H# @

. k% ~) B$ r" I4 c% r* l# A8 t' H: }/ g
1. 硬件连线方式
. w: o7 V7 _1 W% T+ K; K- V4 o    IMX6开发板                        ENC28J60
( w# o6 ~) @4 I0 @' ^+ V' Q8 O) ?: M3 A  Z
CSPI2_CLK        --->               SCK
% O" p- y/ [; E# b$ F2 ^7 w) ~8 o+ Y& f( D. q
CSPI2_MISO      <---                 SO  H# c$ J8 P6 c, n4 L

/ d; A- I$ t* \# R5 w2 k3 MCSPI2_MOSI      --->                  SI2 l( N* y+ T5 i+ q, Q4 P& i0 n
. m7 c" B) \* u) P3 y- `+ ~- L7 n  o
CSPI_CS0          --->                 CS+ m/ b( W9 V1 \4 f; x! l' a9 m
( [8 m# U4 _; ]) ]1 y5 m8 k6 o' b
EIM_D21            <---                  INT. T+ Q8 ]* @" W7 _% x1 c+ q( h
# f  K5 Y3 d5 _+ \5 t/ H  `
VCC  3.3v             --->                VCC
4 J1 D/ a" T8 |+ ]1 }' i( h# O0 d0 C  [  l6 v) D
GND                     -->                 GND9 v& O6 B; ~: R7 ~. y5 h' ?, H
$ A: b9 D* ~7 L3 W+ y: {- t* ~

2 _8 h% k/ Y0 z; h5 d! v5 Y. w% V. Q2 ~; o; @0 m2 D

0 w: e5 M  l7 f( e2 ~2. 初始化引脚
6 L3 }! \+ j+ ?% K9 t从硬件连线方式可以看出,SPI总线使用的是imx6的SPI2控制器,同时额外需要一个GPIO作为中断引脚。( @; C4 E# h4 u0 l& d3 |

, J" G9 m' h6 _# k在原文件arch/arm/mach-mx6/board-mx6q_sabresd.h的数组mx6q_sabresd_pads数组中添加如下内容:& j% Y3 j9 ^; Q7 W1 ~! p; `
. A, v- z- ~9 T
        /* ECSPI2*/
* }  y# {- V8 f5 u# y0 T1 h- p: W        MX6Q_PAD_EIM_CS0__ECSPI2_SCLK,
3 O) B/ i$ e2 d! d9 P& G- Y1 h( K        MX6Q_PAD_EIM_CS1__ECSPI2_MOSI,, x# G" F( L/ o
        MX6Q_PAD_EIM_OE__ECSPI2_MISO,: M6 d+ M" p/ M
        MX6Q_PAD_CSI0_DAT11__GPIO_5_29,        ' ~' G$ o+ y$ G+ ^4 y( W
        //MX6Q_PAD_EIM_D17__GPIO_3_17,1 G) n- ?, h, B  _6 Y, j4 P# y

& R2 x! f, }# o, o* ^' G        MX6Q_PAD_EIM_D21__GPIO_3_21,  /* gpio interrupt for enc2860j */6 }3 a/ O* j# i$ Y- c
5 Q0 G: f, J) @  y
3. 注册SPI控制器和SPI板级设备
& t8 T0 y9 p  ?8 o" {& ^) \由于ENC28J60使用SPI总线,因此,在注册板级设备设备前,需要弄SPI的一些参数。
: J; q) Z' M# L$ f. ^& }2 ?- F, z" q- ]! R3 C6 ~4 t
ENC28J60使用SPI模式0进行传输,最大速率为10Mbps。
* d6 |- H. U8 p6 T6 A
9 m3 d0 w( I. O0 z6 W8 r在原文件arch/arm/mach-mx6/board-mx6q_sabresd.c中添加如下结构体的声明:
9 D) }; ~! p' i  a* x! w
: q/ k- G- g6 z% X0 c7 ^% B/* Following is added by Jone Yim for enc28j60 */
# f7 e( ^- [/ ^! P8 g! d#define SABRESD_ECSPI2_CS0      IMX_GPIO_NR(5, 29)    /* CSPI2_CS0 */
+ \% \! n& \$ c. g. H0 L. S4 N#define ENC28J60_INTERRUPT_GPIO IMX_GPIO_NR(3, 21)    /* EIM_D21 */7 c/ F7 M8 |2 @5 a4 d

% G+ {& @0 R2 w( }" [% [9 a$ H- }static int mx6q_sabresd_spi2_cs[] = {
& i" h: _( T( D  n' O) l        SABRESD_ECSPI2_CS0,
/ f$ [% @/ U3 H6 I};
5 }6 v. d4 G7 B2 h8 z
" U+ P- Z2 W; u7 `( pstatic const struct spi_imx_master mx6q_sabresd_spi2_data __initconst = {0 m/ c- Q0 \( ~
        .chipselect     = mx6q_sabresd_spi2_cs,
, E. n5 e, Y- |1 q$ _        .num_chipselect = ARRAY_SIZE(mx6q_sabresd_spi2_cs),
9 A: F  Z5 Z$ u. B( f8 ?2 }/ X) ^};
5 ?5 N" R) F+ J
6 M5 |: U0 ?2 g7 B1 S7 B9 Y5 \static struct spi_board_info mx6_sabresd_spi2_board[]={; f2 C% j. e: i7 x  P
   [0] = {
. d/ k' E2 w' s' K: ~& b# ^, k             .modalias = "enc28j60",
& @( ^" {) j" Y             .bus_num = 1,
; Z* ~$ D1 Q) e1 F/ s- h7 P             .chip_select = 0,
  R+ I$ Y4 a3 W7 K             .max_speed_hz = 5000 * 1000,% I4 c/ R/ J: z" }# n" c4 t$ |" m
             .mode = SPI_MODE_0,
& @8 S" f' T& H# h2 W    },9 H  }! Q/ d5 j. K

1 z- B, L8 H7 y};
& X5 ~7 H4 J8 I, j" z2 O; u6 x7 [& E; [
! E) P4 z- E$ {; V
首先通过宏定义了CS和INT所使用的引脚号,并定义了SPI板级设备。
7 D; Q5 ]( r6 n; ^* {$ x% x
8 @# |* j. b) M; j接下来我们需要注册该SPI板级设备信息到内核中。
* _3 ~% m8 L: Z/ y$ l
* c+ `  T: a$ A8 m* e在同一文件下的mx6_sabresd_board_init函数中添加如下代码:
5 |/ P! z: ?8 r" b9 M
% M2 B$ r6 ~; T2 w- a/* Following is added by Jone Yim for enc28j60 */- n* C  l2 h1 k; T) F
        imx6q_add_ecspi(1, &mx6q_sabresd_spi2_data); /*using ecspi2*/5 V8 f6 ?- _) C5 K* A) ]
       
# g+ [5 [" S$ W& ]7 B+ ?        ret = gpio_request(ENC28J60_INTERRUPT_GPIO, "ENC28J60-int");  X8 I( v+ t7 Y4 h9 J
        if (ret) {* Q0 s2 m) B$ s& t
                printk(KERN_ERR"request ENC28J60-int error!!\n");
/ N9 n! K9 b7 m0 V4 ^% Q        }else{# J" c- H5 O. ~8 o% y+ R9 a9 S4 W
                gpio_direction_input(ENC28J60_INTERRUPT_GPIO);& t( z; E1 O" \; x; B
               
: \. i. y& B. u  G, h5 Q                //printk("enc28j60 gpio %d irq %d\n", ENC28J60_INTERRUPT_GPIO, irq);- C+ u+ U$ K+ }
                irq = gpio_to_irq(ENC28J60_INTERRUPT_GPIO);) f1 \/ Y" O6 G( H) g8 H
                if(irq < 0){4 ~0 r3 X- u5 x0 j/ u$ x1 g. G( r
                        printk(KERN_ERR"claim gpio irq error!!\n");! E0 b/ m" T+ {! y
                }else{2 I( I" q  k$ B& T) A5 d% Z
                        printk("enc28j60 gpio %d irq %d\n", ENC28J60_INTERRUPT_GPIO, irq);, O: x2 Q5 I7 o0 K, ?* w
                        mx6_sabresd_spi2_board[0].irq = irq;
2 K* A) m$ S! x. [  ?) m                        irq_set_irq_type(irq, IRQ_TYPE_EDGE_FALLING);( @6 a. m0 [9 U
                        spi_register_board_info(mx6_sabresd_spi2_board, ARRAY_SIZE(mx6_sabresd_spi2_board));% \8 H  ?6 t6 m
                }1 G9 S$ ~; p- ]* B! ~! j/ q" h4 S
        }
6 j0 i) v7 H3 ?1 v5 Y$ O  o, Q首先注册SPI2控制器,然后在调用spi_register_board_info注册SPI板级设备信息之前,我们向系统申请了用于中断的GPIO引脚,并获取了其irq号,并将该irq号保存到SPI板级设备信息。
/ z) V/ T- J. s" w: E0 E7 h其次,我们需要设置GPIO的中断类型为下降沿中断,这跟datasheet里面描述的一致。这里提一句为什么要在这里设置中断类型,这是因为在ENC28J60驱动源码的probe方法中并未设置其中断类型,反而是有一段注释要求在bsp中设置中断类型。
3 o7 {& R1 G, N+ k5 w7 R3 j/ p
- h9 F- T% q6 K一切就绪,最后spi_register_board_info调用注册SPI板级设备信息。
3 f) X6 O; p. R" s- B. O
+ ?  w4 C! A* G' j- p! e
6 t1 B# m6 b5 i8 e0 {8 K( ^0 o4 D
4.配置内核
$ g# \5 M, `) H; j1 x% N2 D1 S ( B* x9 d* c: h$ C- [1 I) W
0 G' S7 B; ?4 |7 ^
配置完以后即可编译。
/ g4 k/ A/ H9 a9 |# d
' [2 o! P. S5 Y5 G( D4 s# m( `4 u( [/ U0 D! o$ ], [( G* p
$ O4 ?* ~- @3 Y* `; H2 ]" ~
5.验证
# B4 X7 q, z7 x! Y/ b+ Z' ~8 L8 u系统启动后执行如下命令:
9 g) J: E6 p7 f4 F; s
/ ^, I" u# P) ?* ^, l" d* d6 Yifconfig eth0 down   //关闭原有的网口: _7 U8 a. B9 k* Q3 G6 Y/ \, D

7 I: E. n9 o' N$ w" Hifconfig eth1 up 192.168.0.116   //打开ENC28J60对应的网口并设置IP地址0 O% x% h* z" ?

/ {  m8 M$ Z$ ^, I  t  Q% O8 y
; w. H  c, i1 D5 _1 q
/ ]8 c' y- U0 A% N; P/ F9 X) F然后ping以下虚拟机试试:" p! V" p0 c/ _+ u; y* C  h& s

2 Z: K: H2 A8 h) c. T  d
: _; C: V1 ]3 s$ ^8 q+ R
2 k" b8 m) o7 J, m- B: l' N4 i7 Mping通了,至此大功告成。+ C9 g  N- @8 h  X- u

2 F1 N7 Q3 u" {# ?% A
7 W( x7 `3 Q' S
& n. m4 }$ i, R* Z, {
& d/ r/ _, |& m3 z* V/ F! R
) `# ]6 d: g( K# x8 t; e' `) o  r9 s$ t4 g

作者: NingW    时间: 2020-5-27 17:05
ENC28J60以太网控制器




欢迎光临 EDA365电子论坛网 (https://bbs.eda365.com/) Powered by Discuz! X3.2