ARM Cortex-M3 EMAC以太网控制器:从寄存器配置到DMA驱动的嵌入式网络实战 1. 项目概述在嵌入式系统开发中网络连接能力正变得越来越不可或缺。无论是工业现场的数据采集、智能家居的网关控制还是车载设备的远程诊断以太网都因其高可靠性、高带宽和广泛的标准支持而成为首选。对于基于ARM Cortex-M3这类资源受限的微控制器来说实现以太网功能并非易事它需要在有限的算力和内存资源下高效、可靠地处理网络数据包。这正是集成在芯片内部的以太网媒体访问控制器Ethernet Media Access Controller, EMAC大显身手的地方。它不是一颗外挂的芯片而是作为微控制器的一个片上外设直接通过内部总线与CPU核心、内存以及直接内存访问控制器协同工作为嵌入式设备提供了一个高度集成、低功耗的网络解决方案。简单来说EMAC就是微控制器的“网络协处理器”。它接管了网络数据链路层OSI第二层最繁重、最实时性要求高的任务比如按照精确的时序组帧、拆帧、计算校验码、进行地址过滤等。开发者无需用软件去模拟这些底层且时序严苛的操作只需通过配置一系列寄存器来“告诉”EMAC如何工作并通过读写数据缓冲区来收发网络帧。这极大地降低了开发难度并提升了系统的整体性能和可靠性。本文将深入剖析ARM Cortex-M3内核中常见的EMAC模块以德州仪器相关技术文档为蓝本拆解其工作原理、配置流程和每一个关键寄存器的“脾气秉性”目标是让你不仅能看懂手册更能真正在项目中驾驭它。2. EMAC核心架构与工作原理拆解要熟练配置和使用EMAC绝不能停留在“照抄配置代码”的层面必须理解其内部是如何运转的。这就像开车知道油门和刹车在哪固然重要但了解发动机和变速箱的工作原理才能应对复杂路况。2.1 模块在系统中的地位与数据流EMAC模块在微控制器系统中并非孤立存在它处于一个由CPU、内存、DMA和外部PHY芯片构成的协同工作链中。其核心角色是作为数据链路层MAC层的执行者。数据接收流程物理层芯片PHY通过RJ45接口和网络变压器Magnetics接收到差分电信号将其转换为标准的MII媒体独立接口或RMII精简MII数字信号包括数据线和时钟线。这些信号通过芯片引脚进入EMAC的接收逻辑。EMAC首先进行帧同步识别前导码和帧起始定界符SFD然后按字节流接收数据。接收到的数据被暂存于内部的2KB接收FIFO中。当一帧数据接收完成或达到一定阈值EMAC会通过中断或DMA请求信号通知系统核心有数据待处理。系统软件或μDMA控制器随后从接收FIFO中将整个以太网帧数据读取到系统内存SRAM中的应用程序缓冲区进行进一步处理如解析IP包、TCP/UDP包。数据发送流程应用程序将待发送的网络数据通常是已经封装好的IP数据包准备好存放在系统内存的发送缓冲区中。系统软件或μDMA控制器将这些数据按照EMAC要求的格式后文详述写入EMAC内部的2KB发送FIFO。写入完成后软件触发发送命令。EMAC的发送逻辑开始工作自动为数据添加前导码、SFD并在帧尾计算并附加帧校验序列FCS即CRC32。EMAC将处理完的完整帧通过MII接口的发送数据线按位发送给外部的PHY芯片。PHY芯片将数字信号转换为模拟信号通过网络变压器驱动网线。在整个流程中EMAC的寄存器扮演着“控制面板”的角色而FIFO则是“数据中转站”。理解这两者就抓住了EMAC使用的关键。2.2 核心功能组件详解EMAC内部并非一个黑盒它由几个逻辑上清晰的功能单元构成这些单元通过寄存器进行配置和控制。1. FIFO管理器这是EMAC的数据心脏。它包含一个独立的2KB发送FIFO和一个2KB接收FIFO。发送FIFO用于缓存待发送的一整帧数据。虽然标准以太网帧数据域最大为1500字节但此FIFO实际可容纳最大2032字节的载荷因为帧头14字节占用固定位置。发送时EMAC从此FIFO顺序读取数据并发出。接收FIFO用于缓存从网络接收到的数据帧。它的强大之处在于可以存储多个帧最多31个实现了简单的帧缓冲队列为软件处理提供了时间余量有效防止了因处理不及时导致的丢包。当FIFO满时新到的帧会导致溢出错误。2. 帧处理器这是EMAC的“智能”所在负责以太网帧的封装与解析。发送侧根据配置自动为应用数据添加前导码、SFD并可选择性地自动填充Padding短帧至最小46字节以及自动生成CRC32校验码。这些功能极大减轻了CPU的负担。接收侧校验帧的CRC检查帧长度并根据配置的地址过滤模式如单播、组播、混杂模式决定是否接收该帧。只有通过所有检查的帧才会被放入接收FIFO。3. MII管理接口MIIM这是EMAC与外部PHY芯片通信的“管理通道”。它通过两根线MDC时钟线和MDIO数据线访问PHY芯片内部的寄存器从而配置PHY的工作模式10M/100M、全双工/半双工、重启PHY、读取连接状态和错误信息等。这个接口遵循IEEE 802.3标准是EMAC驱动PHY的标准化方式。4. 中断与DMA控制器接口这是EMAC与系统高效协同的“信使”。中断系统EMAC可以产生多种中断如“收到新包”、“发送完成”、“FIFO溢出”、“CRC错误”等。每个中断源都有独立的使能屏蔽位允许开发者精细控制哪些事件需要CPU立即处理。μDMA接口这是提升性能的关键。EMAC为发送和接收各提供了一个DMA通道请求信号。对于接收当有包存入FIFO时触发请求对于发送当发送FIFO为空可装入新数据时触发请求。通过与芯片内部的μDMA控制器配合可以实现数据在系统内存和EMAC FIFO之间自动搬运CPU仅在开始和结束时介入极大地解放了CPU资源并降低了数据传输延迟。2.3 以太网帧格式与EMAC的交互理解EMAC如何操作数据必须从以太网帧格式说起。一个标准的IEEE 802.3帧结构如下传输顺序从左到右每个字段内低位先传字段长度字节说明前导码 (Preamble)7固定模式10101010...用于接收方时钟同步。帧起始定界符 (SFD)1固定值10101011标志帧正式开始。目的MAC地址 (DA)6数据帧要发送到的设备硬件地址。源MAC地址 (SA)6发送数据帧的设备硬件地址。长度/类型 (Length/Type)2≤1500表示后面“数据”字段的字节数≥1536表示上层协议类型如0x0800代表IPv4。数据与填充 (Data Pad)46-1500上层协议数据。不足46字节时需填充至46字节。帧校验序列 (FCS)4对DA、SA、长度/类型、数据及填充字段计算的CRC32校验码。EMAC与帧格式的交互发送时你只需要通过MACDATA寄存器依次写入目的地址(6字节)、源地址(6字节)、长度/类型(2字节)、数据载荷。如果你使能了自动填充(PADEN1)和自动CRC(CRC1)那么EMAC会自动帮你补足46字节的最小长度并计算、附加4字节FCS。你写入FIFO的“数据长度”字段仅指“数据载荷”的长度。接收时你从MACDATA寄存器读出的第一个字4字节中包含的是整个帧的长度包括14字节帧头和4字节FCS。随后读出的才是目的地址、源地址等。EMAC已经帮你剥离了前导码和SFD并验证了FCS如果使能了BADCRC检查。注意这里有一个极易混淆的细节。发送FIFO的第一个字中的“数据长度”字段指的是你将要发送的“数据载荷”的字节数。而接收FIFO的第一个字中的“帧长度”字段指的是接收到的整个以太网帧从目的地址到FCS的字节数。在编程计算缓冲区大小时务必区分清楚。3. 寄存器详解与配置实战寄存器是软件与EMAC硬件对话的唯一语言。手册中的寄存器描述虽然详尽但缺乏上下文和“怎么用”的指导。下面我将结合常见操作场景对关键寄存器进行“翻译”和实战解读。3.1 控制类寄存器让EMAC动起来这类寄存器负责EMAC的全局使能、工作模式等基础配置。1. 发送控制寄存器 (MACTCTL) - 偏移 0x00C这是配置发送行为的核心。假设系统时钟已使能我们来看一个典型的配置值0x16二进制0001 0110是如何构成的Bit 0 (TXEN): 发送使能。1 开启发送器。这是必须的。Bit 1 (PADEN): 自动填充使能。1 使能。当数据载荷小于46字节时EMAC自动用0填充至46字节。除非你有特殊需求如发送特定格式的测试帧否则强烈建议保持使能以符合IEEE标准。Bit 2 (CRC): CRC自动生成使能。1 使能。EMAC自动计算并附加CRC32校验码。此位必须为1除非你在进行协议一致性测试。手动计算并填充正确的CRC32极其繁琐且易错。Bit 4 (DUPLEX): 双工模式。1 全双工模式同时收发0 半双工模式同一时间只能收或发。此模式必须与PHY芯片协商的实际链路模式一致通常通过MIIM读取PHY状态寄存器获取。配置错误会导致严重的网络性能问题甚至无法通信。2. 接收控制寄存器 (MACRCTL) - 偏移 0x008配置帧过滤和接收行为。典型配置值0x18二进制0001 1000Bit 0 (RXEN): 接收使能。1 开启接收器。Bit 1 (AMUL): 接收组播帧。0 不接收。如果你的应用不需要接收组播包如某些广播发现协议可以关闭以减轻处理负担。Bit 2 (PRMS): 混杂模式。0 关闭。在此模式下EMAC接收所有经过的网络帧无论其目的MAC地址是什么。这常用于网络分析或监听。普通应用务必关闭此模式。Bit 3 (BADCRC): 拒绝错误CRC帧。1 使能。EMAC会丢弃CRC校验失败的帧并产生接收错误中断。必须使能这是保证数据正确性的基本机制。Bit 4 (RSTFIFO): 复位接收FIFO。这是一个只写且自清零的标志位。在初始化时正确的操作顺序是先写RXEN0禁用接收再写RSTFIFO1清空FIFO最后再写RXEN1开启接收。直接写1是无效的。3.2 数据与地址寄存器数据的通道与门卫1. MAC数据寄存器 (MACDATA) - 偏移 0x010这是数据进出FIFO的唯一门户。它是一个“魔法”寄存器读操作访问接收FIFO写操作访问发送FIFO且每次访问后内部的读/写指针会自动递增。实战技巧对齐访问。此寄存器是32位4字节的。尽管以太网帧以字节为单位但EMAC内部FIFO是以字4字节组织的。在写入发送帧或读取接收帧时必须严格按照字对齐的方式操作。例如一个长度为59字节的数据载荷你需要写入ceil(59 / 4) 15个字。最后一个字中未使用的字节应被忽略通常填0。读取时亦然。避坑指南切勿在帧传输过程中即NEWTX置位后但TXEMP中断未产生前写入新的发送数据这会导致数据损坏。同样读取接收FIFO时必须一次性将整个帧读完否则残留数据会影响下一帧的读取。2. 个体地址寄存器 (MACIA0, MACIA1) - 偏移 0x014, 0x018这两个寄存器存储了本设备的6字节MAC地址用于接收时的地址过滤。MAC地址通常由厂商分配或用户自定义。格式详解MACIA0存储地址的低4字节MACIA1存储地址的高2字节位于低16位。例如MAC地址12:34:56:78:9A:BC的存储方式为MACIA0 0x78563412注意字节顺序是反的12 34 56 78在内存中是小端序MACIA1 0x0000BC9A高16位补0存储9A BC配置时机必须在使能接收器(RXEN1)之前配置好这两个寄存器否则过滤功能可能不正常。3.3 状态与中断寄存器系统的耳目1. 原始中断状态/应答寄存器 (MACRIS/MACIACK) - 偏移 0x000这是一个多功能寄存器。读操作返回当前所有未经过滤的中断状态位。写操作则是向特定位写1来清除应答对应的中断标志。关键位RXINT: 接收中断。当有新的帧存入空的接收FIFO时置位。这是最常用的中断通知CPU取数据。TXEMP: 发送FIFO空中断。当一帧数据发送完毕且发送FIFO变空时置位。可用于通知CPU可以准备下一帧数据。RXER: 接收错误中断。原因可能是CRC错误、对齐错误等。FOV: FIFO溢出中断。接收FIFO已满新帧被丢弃。这表明你的软件处理速度跟不上网络收包速度需要优化。清除中断的规范操作在中断服务函数中先读取MACRIS获取状态处理相应事件然后向MACIACK实际是同一地址写入对应的位来清除中断标志。例如清除接收中断MACIACK 0x00000001;。2. 中断屏蔽寄存器 (MACIM) - 偏移 0x004用于使能或禁用特定的中断源向CPU内核申请中断。每一位与MACRIS中的位一一对应。默认值0x7F表示除了PHY中断(PHYINTM0)外其他所有中断都被屏蔽了。因此在初始化时你至少需要使能你关心的中断例如MACIM (1 0); // 仅使能RXINT中断。3. 包数量寄存器 (MACNP) - 偏移 0x034这是一个只读寄存器其低5位(NPR)指示当前接收FIFO中缓存的、已完整接收的帧的数量。这是一个非常有用的轮询标志。当你不使用中断而采用轮询方式时可以不断查询此寄存器当NPR 0时即可开始读取一帧数据。3.4 MII管理接口寄存器与PHY对话的桥梁EMAC通过一组寄存器来管理外部的PHY芯片核心是MACMCTL管理控制、MACMTXD管理发送数据、MACMRXD管理接收数据。1. 管理时钟分频器 (MACMDV) - 偏移 0x024这是配置MII管理接口时钟MDC的关键。MDC频率必须不高于2.5MHz。其计算公式通常为MDC频率 系统时钟频率 / ((MACMDV 1) * 2)。 例如系统时钟100MHz要得到约2.5MHz的MDCMACMDV (100MHz / (2.5MHz * 2)) - 1 19。所以应写入0x13。此寄存器必须在任何MII操作前正确配置。2. 管理控制寄存器 (MACMCTL) - 偏移 0x020用于发起对PHY的读/写操作。REGADR: 指定要读写的PHY寄存器地址0-31。PHYADR: 指定PHY的器件地址通常由PHY芯片的硬件引脚决定常见为0或1。W/R: 操作类型0为读1为写。SCAN: 启动操作。向此位写1EMAC开始一次MII事务。完成后MDINT中断位会置起。标准操作流程读PHY ID为例配置MACMDV。写MACMCTLPHYADR0,REGADR2PHY ID1寄存器地址W/R0读SCAN0。写MACMCTL同时置位SCAN1启动读取。等待MDINT中断或轮询MACRIS的MDINT位。中断发生后从MACMRXD寄存器中读取PHY返回的数据即PHY ID的高16位。4. 初始化与数据收发实战流程理解了各个寄存器后我们将其串联起来形成一个完整的、可操作的初始化及数据收发流程。这里以查询非中断方式为例流程更清晰。4.1 硬件与软件初始化步骤使能外设时钟这是第一步通过系统控制模块的RCGC2寄存器使能EMAC模块和连接MII接口的GPIO端口时钟。没有时钟寄存器访问是无效的。配置MII管理时钟根据主频计算并设置MACMDV寄存器确保MDC时钟 ≤ 2.5MHz。配置MAC地址将本设备的6字节MAC地址写入MACIA0和MACIA1寄存器。复位并配置接收器写MACRCTL 0x0;// 确保RXEN0禁用接收写MACRCTL (1 4);// 置位RSTFIFO1清空接收FIFO。该位会自动清零。写MACRCTL (1 3) | (1 0);// 设置BADCRC1拒收坏帧RXEN1使能接收。可根据需要设置AMUL/PRMS位。配置发送器写MACTCTL (1 4) | (1 2) | (1 1) | (1 0);// 设置DUPLEX1全双工CRC1自动CRCPADEN1自动填充TXEN1使能发送。通常这就是值0x16。可选配置中断如果需要中断方式配置MACIM寄存器使能特定中断源并配置NVIC设置EMAC中断向量和优先级。初始化PHY芯片通过MII管理接口读取PHY ID确认通信正常然后配置PHY的工作模式如自动协商、强制速率/双工、重启PHY等。这部分代码高度依赖具体的PHY芯片型号需查阅其数据手册。4.2 发送一帧数据查询方式假设我们要发送一个ARP请求包数据已准备好放在数组tx_buffer[]中长度为tx_len字节包含14字节以太网头28字节ARP数据共42字节。注意由于使能了PADENEMAC会自动将其填充至46字节。// 1. 等待发送FIFO就绪确保上一帧已发完 // 可以通过检查MACTR寄存器的NEWTX位是否为0或者等待TXEMP中断。 while (MACTR 0x1) { /* 等待NEWTX位清零 */ } // 2. 将帧数据按格式写入发送FIFO (MACDATA寄存器) // 首先写入数据长度仅指数据载荷长度即ARP数据的28字节 uint32_t first_word (tx_len - 14); // 减去14字节的以太网头 MACDATA first_word; // 接着写入6字节目的MAC地址广播地址 FF:FF:FF:FF:FF:FF MACDATA 0xFFFFFFFF; // 低4字节FF FF FF FF MACDATA 0x0000FFFF; // 高2字节FF FF // 然后写入6字节源MAC地址从MACIA0/1中获取或自定义 MACDATA MACIA0; MACDATA MACIA1 0x0000FFFF; // 只取低16位 // 接着写入2字节长度/类型字段对于ARP类型为0x0806 MACDATA 0x0806; // 最后写入ARP数据载荷28字节需要写入7个字 for (int i 0; i 7; i) { uint32_t data_word *(uint32_t*)(tx_buffer[14 i*4]); // 从缓冲区组合字 MACDATA data_word; } // 3. 触发发送 MACTR | 0x1; // 置位NEWTX位启动发送 // 此后EMAC会自动处理填充和CRC添加并将帧发送出去。4.3 接收一帧数据查询方式// 1. 轮询检查是否有新包到达 if ((MACNP 0x1F) 0) { // 检查NPR字段 // 2. 从接收FIFO读取帧头信息 uint32_t frame_info MACDATA; // 第一个字帧长度 uint32_t frame_length frame_info 0xFFFF; // 提取帧总长 uint32_t dest_mac_low MACDATA; // 目的MAC低4字节 uint32_t dest_mac_high MACDATA; // 目的MAC高2字节 填充 uint32_t src_mac_low MACDATA; // 源MAC低4字节 uint32_t src_mac_high_type MACDATA; // 源MAC高2字节 类型/长度 // 3. 计算需要读取的数据载荷长度 // 帧总长 14(DASAType) 数据载荷 4(FCS) uint32_t payload_length frame_length - 18; // 减去14头4FCS // 4. 循环读取数据载荷到应用程序缓冲区 uint32_t words_to_read (payload_length 3) / 4; // 字节数转字数向上取整 for (int i 0; i words_to_read; i) { rx_buffer[i] MACDATA; } // 5. 丢弃帧尾的FCS4字节。由于我们按字读取如果数据载荷不是4的倍数 // 最后一字中已经包含了部分FCS我们需要根据payload_length精确处理。 // 更稳健的做法是读取的字节数严格等于payload_length然后忽略之后的所有内容直到下一帧开始。 // 一个简单的方法是继续读一个字确保读指针对齐到下一帧开始。 volatile uint32_t discard_fcs MACDATA; // 读取并丢弃FCS占用的字 // 此时一帧数据已完整读取到rx_buffer中可供上层协议栈解析。 }4.4 结合μDMA的高效数据传输查询方式会占用大量CPU时间。使用μDMA才是发挥EMAC性能的正道。思路如下接收方向使能EMAC的接收中断(RXINT)。当RXINT中断发生在中断服务程序中启动一次μDMA传输将接收FIFO中的帧长度字和帧头共4个字搬运到一个头部缓冲区。这次传输完成后μDMA产生中断。在中断中解析头部缓冲区得到帧总长度。根据帧长度计算数据载荷长度再启动第二次μDMA传输将剩余的数据载荷从FIFO搬运到最终的数据缓冲区。第二次传输完成后再次产生中断通知应用层处理完整的数据包。发送方向应用层准备好要发送的完整帧数据包括14字节头到发送缓冲区。软件直接启动一次μDMA传输将整个发送缓冲区的数据搬运到EMAC的发送FIFO。传输完成后μDMA产生中断。在中断中软件置位MACTR寄存器的NEWTX位触发EMAC开始发送。也可以利用TXEMP中断在发送完成且FIFO空时通知应用层可以准备下一帧数据。核心心得μDMA的配置特别是源地址、目标地址、传输数据大小的设置需要与EMAC FIFO的访问特性严格匹配。务必使用MACDATA寄存器的地址作为DMA的源/目标地址并确保传输数据大小是4字节的倍数。第一次接收时只搬帧头是为了避免在未知帧长的情况下进行无效的大数据量DMA传输。5. 高级功能与调试排错指南5.1 IEEE 1588精确时间戳对于工业控制、音频视频同步等需要高精度时间同步的应用EMAC支持的IEEE 1588PTP功能至关重要。其核心思想是为每个发送和接收的网络包打上一个极其精确的时间戳。硬件支持原理EMAC模块内部有一个时间戳单元它与芯片的一个通用定时器如GPT3联动。当使能时间戳功能(MACTS.TSEN1)后发送时在帧的第一个比特离开MAC层进入MII接口的精确时刻EMAC会捕获当前GPT3定时器A的值并将其存储起来。应用程序可以在稍后读取这个时间戳。接收时在帧的最后一个比特进入MAC层的精确时刻EMAC会捕获当前GPT3定时器B的值。软件实现要点配置一个GPT定时器工作在32位自由运行模式作为系统的主PTP时钟。配置另一个GPT定时器如GPT3工作在16位边沿捕获模式并将其输出连接到EMAC的时间戳输入。使能EMAC的MACTS.TSEN位。在发送或接收中断中除了处理数据还需要去读取相应定时器的捕获寄存器值这个值就是精确到硬件时钟周期的时间戳。利用PTP协议报文与其他网络设备交换这些时间戳通过算法校正本地时钟实现亚微秒级的同步。5.2 常见问题与排查技巧录在实际开发中EMAC相关的问题往往令人头疼。下面是我总结的一些常见“坑点”和排查思路。问题1链路不通PHY无法连接或协商失败。检查清单时钟与复位确认EMAC和GPIO模块的时钟已使能。确认PHY芯片的复位引脚已正确释放。MII接口连接仔细核对原理图确认TXD、RXD、TX_CLK、RX_CLK、CRS、COL等信号线是否正确连接到MCU的指定引脚且没有交叉。MII管理通信这是第一步。编写代码读取PHY的ID寄存器通常地址2和3。如果读不到正确的ID说明MDC/MDIO通信失败。检查MACMDV分频配置是否正确MDC时钟是否正常。用逻辑分析仪抓取MDC和MDIO波形看是否有读写时序数据是否正确。PHY配置成功读取ID后配置PHY。如果使用自动协商读取状态寄存器确认是否已链接Link Up以及协商出的速率和双工模式。确保与EMAC的MACTCTL.DUPLEX配置一致。电气与隔离检查网络变压器中心抽头是否接对电源是否干净。这是硬件问题的高发区。问题2可以发送数据但接收不到数据或者反之。排查思路环回测试将EMAC配置为内部环回模式如果支持或者短接PHY的发送和接收线。先排除软件驱动问题。中断与状态检查MACRIS寄存器看是否有RXINT或RXER等中断标志置位。如果没有可能帧在过滤环节就被丢弃了。地址过滤检查MACIA0/1寄存器配置的MAC地址是否正确。如果对方发送的是广播帧(FF:FF:FF:FF:FF:FF)确保你的MAC地址不是广播地址。尝试开启混杂模式(PRMS1)看是否能收到所有包。如果能问题就是地址过滤。FIFO操作确保接收FIFO已在初始化时清空(RSTFIFO)。在读取数据时是否严格按照字对齐读取是否读取了完整的帧包括最后的FCS未读完的残留数据会破坏下一帧。数据验证使用网络抓包工具如Wireshark在发送端和接收端抓包对比发送的数据和对方实际收到的数据是否一致。可以发送固定的测试帧如全AA或全55来观察。问题3通信不稳定偶尔丢包或出错。深度排查中断服务程序是否处理得太慢是否在中断中做了太多事情确保ISR尽可能短只做标志位处理和启动DMA繁重的数据处理放到主循环。检查是否丢失了中断未及时清除标志。FIFO溢出检查MACRIS的FOV位是否置位。如果频繁溢出说明接收速度大于处理速度。优化代码或者使用更大的接收缓冲区并确保及时取走FIFO中的数据。DMA配置如果使用DMA检查DMA传输的源/目标地址、数据宽度、突发大小是否配置正确。DMA传输是否与CPU访问内存产生了冲突考虑使用带缓冲的内存区域或调整DMA优先级。时钟与电源检查系统主频和EMAC外设时钟是否稳定。在低功耗模式下如果EMAC时钟被关闭或降频会导致通信失败。确保在收发数据期间相关时钟域处于活动状态。PCB布线对于100Mbps以太网MII接口的时钟线25MHz和数据线已属于高频信号。检查PCB布线确保时钟和数据线走线等长、短且完整远离噪声源并做好阻抗控制。调试EMAC是一个系统工程需要软件、硬件、工具协同。准备好逻辑分析仪、示波器和网络调试工具从最简单的MII管理通信开始逐步验证发送、接收、中断、DMA每一个环节是解决问题的唯一捷径。每一次排错的过程都是对这套复杂系统理解加深的过程。