网络通信的作用不用多说,而这次进行的工作即是对以太网通信过程中,需要用到的硬件部分进行初始化,也介绍了发送和接收数据的方法。

由于较为复杂,所以使用了ASF框架。但是也会对用到的库函数的实现做一个介绍。

一、 MAC、PHY和MII

IEEE 802.3是现在常用的以太网标准,它定义了物理层(Physical Layer, PHY)和介质访问控制层(Media Access Control, MAC)的标准。另外,在OSI模型中,MAC则处于数据链路层的底层

而在硬件实现上,M4使用的GMAC外设实现了802.3中MAC的功能。开发板携带型号为KSZ8051MNL的PHY芯片以及RJ45接口则实现了物理层的功能:

MAC和PHY之间交互的接口则是介质独立接口(Media Independent Interface,MII)。MII包含一个数据通信接口,以及一个管理接口(Management Data Input/Output ,MDIO)。由于PHY的接口是面向MAC的,所以我们需要通过MAC来对PHY进行管理及数据交互。

另外,更早制定的Ethernet II则是现在以太网传输中常使用的帧格式。

二、 GMAC的DMA缓冲区

GMAC使用了一个DMA接口。和M4的通用DMAC一样,它也可以自动进行多次传输,但是方式稍微有点区别。GMAC的DMA 对发送和接收使用不同的缓冲区列表,而缓冲区描述符列表是一个数组,而不是DMAC所使用的链表。数组的起始位置保存在寄存器(GMAC_RBQBGMAC_TBQB)中,且缓冲区描述符中有一个字段(Wrap)指示其是否为数组中的最后一个描述符。如接收缓冲区:

在工作过程中,DMA会顺序访问每个缓冲区描述符,而在访问最后一个描述符时,就会重新开始遍历。

对于接收缓冲,列表中每一个缓冲区的长度是一样的,这个长度由DMA配置寄存器(GMAC_DCFGR)中的DRBS字段指定。在DMA将数据写入接收缓冲时,也会设置描述符相应的字段,以表明每帧的起始与结束;同时,也会标注相关的信息,如是否为广播帧等。

对于发送缓冲,其帧长度、是否需要添加CRC等控制信息也均在描述符中表示。在准备好数据后,向GMAC_NCR寄存器写入TSTART字段即可触发发送操作。

三、 使用ASF初始化GMAC

由于PHY是通过MAC访问的,所有在设置PHY前要完成GMAC的设置。

GMAC约有94个寄存器,其中约有40个为统计寄存器,约15个寄存器与1588和PTP相关,约15个寄存器与特殊地址和ID有关。另外,在有些状态寄存器中,需要向特定位写入1才会清除该位的状态。

使用的ASF模块为Ethernet GMAC,然后conf_eth.h中可以设置MAC地址,IP地址,子网掩码,网关以及缓冲区大小等参数。

然后调用gmac_dev_init( ) 函数即可对GMAC进行初始化:

pmc_enable_periph_clk(ID_GMAC);
// MAC地址
uint8_t mac_address[] =
{ ETHERNET_CONF_ETHADDR0, ETHERNET_CONF_ETHADDR1,
ETHERNET_CONF_ETHADDR2,ETHERNET_CONF_ETHADDR3,
ETHERNET_CONF_ETHADDR4, ETHERNET_CONF_ETHADDR5
};
// GMAC选项
gmac_options_t gmac_option;
gmac_option.uc_copy_all_frame = 0; // 不拷贝所有帧
gmac_option.uc_no_boardcast = 0; // 不忽略广播
memcpy(gmac_option.uc_mac_addr,
mac_address, sizeof(mac_address)); //拷贝MAC地址
// GMAC驱动设置
gmac_device_t gmac_dev;
gs_gmac_dev.p_hw = GMAC; // 指定GMAC寄存器基址
// 初始化GMAC
gmac_dev_init(GMAC, &gmac_dev, &gmac_option);

gmac_dev_init(Gmac* p_gmac, gmac_device_t* p_gmac_dev, gmac_options_t* p_opt) 函数完成了以下的工作:

  1. 禁用发送接收,禁用GMAC所有中断;清除统计寄存器,以及发送接受状态寄存器。
  2. 设置GMAC_NCFGR寄存器。根据p_opt,判断是否拷贝所有帧,以及是否忽略广播。同时,追加GMAC_NCFGR_PENGMAC_NCFGR_IRXFCS位。(我觉得这里应该是个BUG,从其注释判断需要追加的应该是GMAC_NCFGR_RFCS位)
  3. 设置好DMA缓冲,然后调用gmac_init_mem( ) 对缓冲区描述符等进行初始化。这个函数里也会使能发送和接收,同时也会启用一系列的中断。设置完成后,DMA缓冲的信息将储存在p_gmac_dev中。
  4. MAC地址写入特别地址寄存器1。

四、 PHY的地址

在MDIO通信过程中,每个PHY都会有一个4位的地址。而开发板携带的KSZ8051MNL芯片,可以在上电或复位时,根据引脚设置地址的低3位:

在开发板中,上电时PHYAD[2:0]的值为001,即其地址为0x1

特别指出,地址0可作为该芯片的广播地址,而开发板也做了这样的配置。另外,在ASF中,错误地将PHY的地址定义成了0。这样能正确工作的原因仅是0为广播地址,而开发板只有一个PHY芯片。严谨起见,将这个地址修改为正确的值:

#ifdef BOARD_GMAC_PHY_ADDR
#undef BOARD_GMAC_PHY_ADDR
#endif
#define BOARD_GMAC_PHY_ADDR 1

五、 ASF中使用PHY

使用的模块为Ethernet Physical Transceiver。需要在conf_board.h 中声明宏:

/* 使用 ETH PHY: KSZ8051MNL */
#define CONF_BOARD_KSZ8051MNL
  1. 初始化。

    在PHY上电后,需要等待一段时间让其运行稳定。之后就可以对其进行初始化了:

    if (ethernet_phy_init(GMAC, BOARD_GMAC_PHY_ADDR,sysclk_get_cpu_hz())
    != GMAC_OK) {
    puts("PHY Initialize ERROR!\r");
    return -1;
    }

    在该ethernet_phy_init( ) 函数中,完成了以下工作:

    1. 设置MDIO的时钟MDC。
    2. 通过MDIO向PHY发送重置命令。
    3. 检查地址是否正确。检查的逻辑是先读取PHY的PHYID1的内容,再判断读出的内容是否正确。KSZ8051MNL芯片中,该寄存器的值是0x22。
    4. 如果地址无效的话,因为MDIO有效地址只有32个,就遍历这些地址。然后使用检查出的新地址重新发送一次重置命令。
    5. 如果初始化成功,则返回GMAC_OK。
  2. 自协商。

    然后需要让PHY协商通信速率、双工模式:

    ethernet_phy_auto_negotiate(GMAC, BOARD_GMAC_PHY_ADDR);
    if (ethernet_phy_set_link(GMAC, BOARD_GMAC_PHY_ADDR, 0)
    != GMAC_OK) {
    puts("Set link ERROR!\r");
    return -1;
    }

    ethernet_phy_auto_negotiate() 函数就会完成PHY的协商工作,然后根据协商的结果设置GMAC的速率、双工模式。ethernet_phy_set_link() 函数则会检查链路的状态,同时可以根据参数(第3个)应用PHY的自协商结果至GMAC中。

  3. 中断处理。

    ASF的GMAC模块需要获取相关的中断,以进行相关的工作:如更新发送缓冲区描述符相关的信息,或是调用用户定义的回调函数等。

    // 需要在NVIC中启用相关中断
    void GMAC_Handler(void)
    {
    gmac_handler(&gs_gmac_dev);
    }
  4. 数据接收。

    先准备好一个缓冲,然后就可以调用gmac_dev_read() 读取出接收到的帧的内容。

    //#define GMAC_FRAME_LENTGH_MAX       1536
    uint8_t eth_buffer[GMAC_FRAME_LENTGH_MAX];
    uint32_t frm_size;
    gmac_dev_read(&gmac_dev, (uint8_t *) eth_buffer,
    sizeof(eth_buffer), &frm_size);
  5. 数据发送。

    gmac_dev_write(&gmac_dev, (uint8_t *)eth_buffer, frm_size, NULL);

    通过该函数即可使用GMAC发送数据,第4个参数是发送完成后的回调函数。该回调函数时是在gmac_handler() 中被调用的。

SAM4E单片机之旅——22、GMAC和PHY的介绍与初始化的更多相关文章

  1. SAM4E单片机之旅——24、使用DSP库求向量数量积

    DSP(Digital Signal Processing,数字信号处理)中会使用大量的数学运算.Cortex-M4中,配置了一些强大的部件,以提高DSP能力.同时CMSIS提供了一个DSP库,提供了 ...

  2. SAM4E单片机之旅——23、在AS6(GCC)中使用FPU

    浮点单元(Floating Point Unit,FPU),是用于处理浮点数运算的单元. 为使用FPU,除了需要启用FPU外,还需要对编译器进行设置,以使其针对浮点运算生成特殊的指令.虽然在Atmel ...

  3. SAM4E单片机之旅——18、通过AFEC(ADC)获取输入的电压

    很多时候,一个电压不仅仅需要定性(高电平或者低电平),而且要定量(了解具体电压的数值).这个时候就可以用到模数转换器(ADC)了.这次的内容是测量开发板搭载的滑动变阻器(VR1)的电压,然后把ADC转 ...

  4. SAM4E单片机之旅——13、LCD之ASF初步

    在Atmel Studio 6中,集成了Atmel Software Framework(ASF框架).通过它提供的库,可以很快速地完成新的项目. 这次的最终目标使用ASF在LCD上显示出文字“Hel ...

  5. SAM4E单片机之旅——3、LED闪烁之定时器中断

    让一个LED灯闪烁不过瘾,我们应该让这块开发板完成一点更高难度的任务:比如让两个LED灯闪烁. …… 当然了,以我们的现在使用的空循环技术,还是可以实现这点的.但是这样显得略为低端.所以我们使用一个高 ...

  6. SAM4E单片机之旅——2、LED闪烁之轮询定时器

    之前我们使用空循环,达到了延迟的目的,但是这样子的延迟比较不精确.现在就使用实时定时器(RTT)来进行更为精确的计时.RTT虽然不是特别通用,在某些单片机上可能没有,但它较为简单. RTT内部有一个计 ...

  7. SAM4E单片机之旅——1、LED闪烁之空循环

    最近因为导师要写一本关于SAME4单片机的书籍,而我也作为一个嵌入式的初学者看了这本书.现在也让我写写几个小的程序,做做示例.既然写了文档之类的,就发到博客上来吧. 目前关于这芯片能参考的书籍大概就只 ...

  8. SAM4E单片机之旅——21、DMAC之USART回显

    DMAC也可以和外设进行数据交互.之前我们曾使用PDC进行USART的数据回显,这次就使用DMAC完成相同的工作.而且由于DMAC有内部的缓冲区,实现起来更为简单. 一. USART设置 因为之前已经 ...

  9. SAM4E单片机之旅——20、DMAC之使用Multi-buffer进行内存拷贝

    这次使用这个DMAC的Multi-buffer传输功能,将两个缓冲区的内容拷贝至一个连续的缓冲区中. 一. DMAC 在M4中,DMA控制器(DMAC)比外设DMA控制器(PDC)要复杂,但是功能更加 ...

随机推荐

  1. Love

    愿这段代码陪我走过此生,献给我最爱的榨菜. /** *@Description:<p>我爱榨菜</p> *@author 王旭 *@time 2016年4月25日 下午7:58 ...

  2. Android 学习笔记之AndBase框架学习(六) PullToRefrech 下拉刷新的实现

    PS:Struggle for a better future 学习内容: 1.PullToRefrech下拉刷新的实现...   不得不说AndBase这个开源框架确实是非常的强大..把大部分的东西 ...

  3. 三、Authentication & sessionid

    客户在访问Django的某些敏感资料时,被要求需要先登录,客户通过/admin/login进行登录,客户登录成功后,Django给客户分配一个sessionid,后续的访问过程,客户端只需在http头 ...

  4. scrum1.4---Sprint 计划

    燃尽图

  5. 对Mathsapp的测试以及找bug

    组员博客地址: 练思明 卓嘉炜:http://www.cnblogs.com/luoliuxi/ 何宇明:http://www.cnblogs.com/40heyuming/ 团队贡献分: 练思明:2 ...

  6. thread_LockSupport

    LockSupport是用来创建锁和其他同步类的基本线程阻塞原语. LockSupport中的park() 和 unpark() 的作用分别是阻塞线程和解除阻塞线程,而且park()和unpark() ...

  7. 【循序渐进学Python】13.基本的文件I/O

    文件I/O是Python中最重要的技术之一,在Python中对文件进行I/O操作是非常简单的. 1. 打开文件 使用 open 函数来打开文件,语法如下: open(name[, mode[, buf ...

  8. 泛函编程(14)-try to map them all

    虽然明白泛函编程风格中最重要的就是对一个管子里的元素进行操作.这个管子就是这么一个东西:F[A],我们说F是一个针对元素A的高阶类型,其实F就是一个装载A类型元素的管子,A类型是相对低阶,或者说是基础 ...

  9. php学习笔记:利用递归实现删除文件目录

    直接删除目录,如果是空目录是可以删除,如果不是空目录,这时候只能先删除目录里面的文件,然后再删除目录.我封装了个删除函数,然后直接调用这个函数.喜欢的可以直接拿去用,编码是gbk的,使用时候注意下编码 ...

  10. SharePoint 禁用本地回环的两个方法

    有两种方法中,若要变通解决此问题,请根据您的具体情况使用下列方法之一. 方法 1: 指定主机名 (如果需要 NTLM 身份验证,请首选方法) 指定的主机名的映射到环回地址,并可以连接到 Web 站点在 ...