uboot移植与源码分析总结(4)-以太网驱动

转载:http://www.eefocus.com/lishutong/blog/13-06/295363_c502a.html


虽然此文名为移植,但实际的工作量很小,只需简单修改即可完成tiny210板上的以太网驱动程序移植。

tiny210开发板上板载DM9000网络芯片,集成了网络控制器和PHY,外接一个网络变压器。uboot源码目录driver/net提供了驱动程序dm9000x.c/dm9000x.h。由于DM9000通过SRAM接口挂接在s5pv210的SROM端口1上,16位总线模式;所以从思路上来说,只需要将dm9000驱动程序加入Uboot编译中,并且在uboot初始化时打开SROM端口1,并注册dm9000驱动程序,s5pv210即可访问dm9000内部寄存器。

以太网设备抽像结构及其注册

uboot对以太网设备的抽像和对串口设备的抽像方法很类似(串口设备抽像见UBoot的Serial驱动分析),每个以太网设备用struct eth_device结构表示。struct eth_device定义如下:

struct eth_device { 
    char name[16]; 
    unsigned char enetaddr[6]; 
    int iobase; 
    int state;

    int  (*init) (struct eth_device *, bd_t *); 
    int  (*send) (struct eth_device *, void *packet, int length); 
    int  (*recv) (struct eth_device *); 
    void (*halt) (struct eth_device *); 
#ifdef CONFIG_MCAST_TFTP 
    int (*mcast) (struct eth_device *, u32 ip, u8 set); 
#endif 
    int  (*write_hwaddr) (struct eth_device *); 
    struct eth_device *next; 
    int index; 
    void *priv; 
};

如果要支持多个以太网设备,则需定义多个struct eth_device,然后通过调用eth_register(device)向uboot注册该结构。所有注册的设备被加入到eth_devices所指向的链表中,eth_current指向当前的设备,这种组织方式和serial驱动类似。

static struct eth_device *eth_devices;     // 位于net/eth.c 
struct eth_device *eth_current;

imageDM9000x.c中包含完成了定义结构和注册工作的初始化函数,我们只需要调用:

int dm9000_initialize(bd_t *bis) 

    struct eth_device *dev = &(dm9000_info.netdev);

    /* Load MAC address from EEPROM */ 
    dm9000_get_enetaddr(dev);

    dev->init = dm9000_init; 
    dev->halt = dm9000_halt; 
    dev->send = dm9000_send; 
    dev->recv = dm9000_rx; 
    sprintf(dev->name, "dm9000");

    eth_register(dev);

    return 0; 
}

由于uboot的工作机制比较简单,不需要过于考虑效率,因而DM9000的驱动函数实现也比较简单。主要完成初始化、停止、发送帧、接收帧等操作。

s5pv210上DM9000驱动程序移植

移植步骤很简单,除了将DM9000x.c加入到uboot源码编译中外,还需要在某个地方初始化DM9000所在的SROM端口1以及调用dm9000_initialize()。

我认为这些初始化调用不能随便加入到源码中的某个位置,uboot应该有它自己的流程。所以,分析了下net/eth.c源码,因为这部分与硬件最为接近,发现int eth_initialize(bd_t *bis)完成整个以太网驱动硬件底层初始化。而其中就有调用board_eth_init(),从该函数的字面意思来看是完成与目标板相关的以太网驱动初始化。而该函数的缺省实现是直接返回错误,即初始化失败。

static int __def_eth_init(bd_t *bis) 

    return -1; 
}

int cpu_eth_init(bd_t *bis) __attribute__((weak, alias("__def_eth_init"))); 
int board_eth_init(bd_t *bis) __attribute__((weak, alias("__def_eth_init")));

依照uboot的源码风格,board_eth_init是可以被重向定义的。于是我重新定义了该函数,并将相关的初始化操作放在里面。

int board_eth_init(bd_t *bis) 

    int ret = 0;

    SROM_BW_REG &= ~(0xf << 4); 
    SROM_BW_REG |= (0<<7) | (0<<6) | (1<<5) | (1<<4);  // SROM_ADDR[22:0] <= HADDR[23:1],16位总线 
    SROM_BC1_REG = ((0<<28)|(1<<24)|(5<<16)|(1<<12)|(4<<8)|(6<<4)|(0<<0)); 
    ret = dm9000_initialize(bis); 
    return ret; 
}

通过上面的两步,即完成了以太网驱动程序的移植。

UDP/IP协议栈概述

UBoot提供了一个简单的网络协议栈,所有源码位于net目录下。实现的协议有ARP、IP、UDP、ICMP、bootp、nfs、rarp、tftp,没有实现tcp协议。所以说,这个协议只能称作是UDP/IP协议栈,而不能称作TCP/IP协议栈。

类似的协议栈我在大学里实现过一个,当时能实现ping操作、tftp文件传输,实现比较简单,跟uboot的实现类似。所以,这里不做详细分析。

一般而言,在初始完成移植后,常使用ping来完成基本通信测试。ping命令基于IP/ICMP协议,首先会向目标IP地址的主机发送一个ICMP数据包,目标主机收到响应后会将该数据包原样返回,如果uboot接收到该数据包,即认为和主机已经连通。

如果不能ping通,有可能是驱动程序根本就没有把ICMP数据包发出去,或者是发送了错误的数据包,也有可能是发出去了但主机没有收到或者没有发送响应。这里就需要借助以太网抓包工具来抓取网络上的整个数据流,才能进一步分析是何种原因。抓包工具推荐使用wireshark,软件截图如下:

image

uboot驱动程序移植的总结

 

移植完后,使用tftp传输文件,大概250KB/s,速度还行。这个驱动程序的移植看起来没有太多技术含量。源码都有,要做的只不过是修改后能在特定的目标板上运行。

移植本身并不复杂,uboot的doc目录下有相关的说明文档;外加源码开放,如有不理解的,可参考其它目标板的移植。这样通过参考、修改就可完成这个移植过程。

无论是移植何种驱动,移植的工作均可以分成两块,先是熟悉硬件、实现驱动接口函数;而后才是按照uboot的源码格式要求编写。前者需要通用的技术基础,跟任何bootloader、os都无关,取决于自己是否对硬件能有深入地理解;而后者只不过是适应一种软件框架。

所以,从我目前学习和理解uboot的目的出发,接下来的USB驱动、NAND驱动程序移植中,以熟悉uboot驱动框架为主,不深究硬件细节。


  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: u-boot是一个开源的引导加载程序,用于嵌入式系统的启动。它通常嵌入在芯片的ROM或闪存中,是系统的第一个执行程序,负责初始化硬件、加载操作系统和其他应用程序。 u-boot源码是以C语言编写的,具有高度可移植性。它提供了一系列的驱动程序和命令行工具,可以在开发板上进行硬件初始化和测试。 源码的结构分为几个重要的部分:启动代码、中断向量表、初始化代码以及其他功能模块。启动代码是u-boot执行的入口点,在这个阶段,它会初始化一些必要的硬件设备,例如串口、存储器等,同时也会设置中断向量表。 中断向量表是一个由硬件中断信号触发的函数指针数组,u-boot将中断信号与相应的函数关联起来,以便在发生中断时进行相应的处理。 初始化代码是u-boot执行的核心部分,它会通过配置文件或环境变量来读取系统设置,并进行相应的初始化。例如,它会加载并运行操作系统内核镜像,设置内存映射表,配置设备和网络接口等。 此外,u-boot还提供了一些功能模块,例如命令行解析器、文件系统支持、网络协议栈等。这些功能模块可以通过命令行进行操作,以便用户对嵌入式系统进行配置、调试和测试。 对于研究和分析u-boot源码,可以从以下几个方面入手: 1. 启动流程:了解u-boot是如何从ROM或闪存中加载到内存并执行的,包括启动代码和中断向量表的设置。 2. 硬件初始化:了解u-boot是如何初始化硬件设备的,包括串口、存储器、网络接口等。 3. 配置文件和环境变量:了解u-boot是如何通过配置文件或环境变量来读取系统设置的,以及如何进行相应的初始化。 4. 功能模块:了解u-boot提供的功能模块,例如命令行解析器、文件系统支持、网络协议栈等,以及它们的实现方式和使用方法。 通过对u-boot源码的详细分析,可以深入了解嵌入式系统的引导过程、硬件初始化和驱动程序的编写,从而提高嵌入式系统的开发和调试能力。 ### 回答2: Uboot是一种开源的引导加载程序,用于嵌入式系统的启动。它是一个简单而灵活的软件,可以在各种硬件平台上使用,并提供了许多功能和驱动程序。 首先,Uboot的主要功能是加载和运行操作系统。它通过读取存储介质上的引导扇区,将操作系统加载到内存中并启动。此外,Uboot还提供了命令行界面,用户可以在启动过程中进行配置和控制。 Uboot的源代码由若干模块组成,包括引导代码、设备驱动程序、命令行解析器等。其中,引导代码是最关键的部分,负责在硬件启动时初始化系统和设备,并在引导过程中进行加载和启动操作系统。设备驱动程序用于访问硬件设备,例如存储介质、串口等。命令行解析器则负责解析用户输入的命令,并执行相应的操作。 在Uboot的源代码中,可以找到各种初始化和设置函数,以及与硬件平台相关的代码。这些代码通常是与硬件设备的寄存器交互,进行硬件初始化和配置。此外,还有一些与引导过程和加载操作系统相关的代码,用于读取、解析和加载引导扇区以及操作系统镜像。 总的来说,Uboot源码详细分析涉及到引导代码、设备驱动程序和命令行解析器等多个模块。在分析过程中,需要理解硬件平台的相关知识和操作系统的启动流程,并深入了解Uboot的代码实现和功能。只有这样,才能对Uboot源码有一个全面的理解,并能根据需求进行相应的修改和定制。 ### 回答3: U-Boot是一款开源的引导加载程序,用于嵌入式系统中启动操作系统。它是最常用的引导加载程序之一,具有广泛的应用。下面,我将对U-Boot源码进行详细分析。 U-Boot源码位于一个git仓库中,可以通过clone仓库获取源码源码的结构清晰,主要分为三个部分:板级支持包(board support package,BSP),引导和命令。 BSP包含了与硬件相关的代码和配置文件,用于支持不同的硬件平台。其中,包括设备初始化、设备驱动程序和硬件设置等。这些代码主要包括处理器启动代码、时钟初始化、内存初始化以及设备和外设的配置等。 引导部分是U-Boot的核心,其中包括引导过程的各个阶段。首先,它加载引导扇区和主引导程序,其中包括引导加载器。引导加载器根据设备的启动模式选择适当的引导方式。然后,它会加载内核映像和根文件系统,并将控制权转移到内核。 最后,命令部分包含了一系列的命令,用于与用户进行交互。这些命令可以用于启动操作系统、进行系统设置和调试等。U-Boot提供了丰富的命令集,包括boot、setenv、saveenv、printenv等等。 在分析U-Boot源码时,需要了解硬件平台的特性和配置文件。可以根据目标硬件平台的手册和数据手册,对源码进行逐步分析和调试。在分析过程中,可以使用调试工具进行跟踪、断点和单步调试,以便更好地理解源码的执行过程。 总的来说,U-Boot源码的详细分析需要涉及到硬件平台的特性和配置文件,并对引导加载过程和命令解析进行深入研究。通过对U-Boot源码的理解和分析,可以为嵌入式系统的启动和操作提供更好的支持和定制化。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值