API GUIDE / MAC / OVERVIEW

G32S10 MAC API 概述

模块概述:本文档定义 G32S10 SDK 当前 Ethernet MAC(GMAC)模块的 HAL 与 LL 正式接口,覆盖:

1. 文档范围

本文档定义 G32S10 SDK 当前 Ethernet MAC(GMAC)模块的 HAL 与 LL 正式接口,覆盖:

  • HAL MAC:面向 BSP、驱动适配层和网络中间件的 MAC/DMA/MDIO 功能级接口

  • LL MAC:面向 GMAC 寄存器与位操作的低层 static inline 接口

  • mac_regs.h:GMAC 寄存器布局、位域 mask、实例与基地址定义

本文档基于以下实现与头文件编写:

文件层次说明
code/include/drivers/g32s10/mac/hal_mac.hHAL MAC19 个公开 HAL 函数、公开宏、枚举、配置/描述符/统计/句柄结构体
code/include/drivers/g32s10/mac/ll_mac.hLL MAC全部 static inline 寄存器访问接口
code/include/drivers/g32s10/mac/mac_regs.h寄存器定义寄存器结构体、实例宏、基地址、全部位域 mask
code/drivers/g32s10/mac/hal_mac.cHAL MAC初始化、状态机、超时、描述符协议、DMA、RX FCS、MDIO、IRQ、调试 dump
code/drivers/g32s10/mac/Kconfig构建配置CONFIG_DRIVER_MAC、CONFIG_MAC_ENABLE_DEBUG_HELPERS
code/drivers/g32s10/mac/CMakeLists.txt构建脚本组件名 g32s10_mac,源文件 hal_mac.c

补充说明:HAL 层负责描述符环与缓冲区管理、DMA/MAC 基本编程、MDIO 访问、DMA 数据通路中断状态处理、统计和调试 dump,不负责 CPM 时钟门控、MAC 软复位、SoC IRQ 注册与 PLIC 配置、PHY 驱动语义、链路自动协商和 lwIP 接入;LL 层接口全部为 static inline,直接读写寄存器,不做参数保护、不维护软件状态、不实现业务语义;本文档只定义 HAL/LL 接口契约、寄存器布局和位域约定,MAC 与 PHY、lwIP 的整体数据流见 docs/api/g32s10/middleware/mac_mid_api.md。

2. 分层关系

APPLICATION  Application / BSP / Driver  业务代码、板级支持与示例入口
↓
HAL  HAL MAC  模块级配置、状态管理与硬件访问
↓
LL  LL MAC  寄存器访问与字段级控制
↓
HARDWARE REGISTERS  GMAC Registers / DMA / MDIO  实例地址、寄存器布局与位域定义
↓
HARDWARE  External PHY / Ethernet  板外器件或硬件连接边界

分层职责:Application / BSP / Driver 负责 CPM 时钟门控、MAC 软复位、管脚复用、PHY 驱动与链路管理,提供对齐的描述符/缓冲区,注册并使能 IRQ_GMAC 并在 IRQ 入口调用 hal_mac_irq_handler();HAL MAC 封装单实例 GMAC 的初始化、启停、TX/RX 描述符环、DMA、MDIO、流控、统计和调试,维护句柄状态与描述符索引,并负责描述符/缓冲区 cache 维护;LL MAC 只提供寄存器位级访问,调用方必须保证实例指针有效、参数已按位域裁剪、并发访问已串行化;mac_regs.h 定义 mac_regs_t 寄存器结构体、实例宏 MAC、基地址 GMAC_IOBASE 和全部位域 mask。

与上层模块的边界:

边界归属说明
CPM 时钟门控与 MAC 软复位BSP + CPM 驱动hal_cpm_clk_enable(HAL_CPM_ID_GATE_MAC)、ll_cpm_set_mac_soft_reset()、ll_cpm_clear_mac_soft_reset()
描述符与缓冲区内存调用方调用方提供,HAL 只编程与维护 cache
PHY 寄存器语义与自动协商PHY 驱动HAL 只提供 Clause 22 MDIO 读写
链路状态与速率决策PHY 驱动 / Ethernet adapterHAL 只按请求写 MAC_CR 速率/双工位
SoC IRQ 注册、优先级与使能调用方im_irq_request(IRQ_GMAC, ...)、im_irq_set_priority()、im_irq_enable()
lwIP netif 与 pbuf 数据路径Middleware见 docs/api/g32s10/middleware/mac_mid_api.md

3. 资源模型与公开类型

3.1 模块实例与基地址

项目值/宏说明
实例宏MAC((mac_regs_t *)(uintptr_t)GMAC_IOBASE)
基地址宏GMAC_IOBASE0x134B0000
地址空间64 KBbase.h 注释标注为 64KB GMAC/MAC
IRQIRQ_GMACIRQ_PLIC0_START + 11,当前 IRQ_PLIC0_START == 0,即软件 IRQ 号 11
CPM 时钟门控HAL_CPM_ID_GATE_MAC由 BSP 通过 hal_cpm_clk_enable() / hal_cpm_clk_disable() 控制
MAC 地址寄存器数量MAC_ADDRESS_REGISTER_COUNT2U
实例检查IS_MAC_ALL_INSTANCE(INSTANCE)映射到 ll_mac_is_instance(INSTANCE),仅比较 macx == MAC
#define MAC  ((mac_regs_t *)(uintptr_t)GMAC_IOBASE)
#define MAC_ADDRESS_REGISTER_COUNT  2U

说明:G32S10 当前只暴露 1 个 Ethernet MAC 实例,hal_mac_handle_init() 在内部直接绑定 MAC,调用方无需传实例指针。

3.2 HAL 公开宏

宏取值说明/约束
IS_MAC_ALL_INSTANCE(INSTANCE)映射到 ll_mac_is_instance()判断 mac_regs_t * 是否为受支持实例
HAL_MAC_ADDRESS_SIZE6UEthernet MAC 地址字节数
HAL_MAC_DEFAULT_MTU1500U默认 Ethernet MTU
HAL_MAC_MAX_MTU2000UHAL 接受的最大 MTU
HAL_MAC_MIN_DESCRIPTOR_COUNT2UTX/RX 描述符环各自的最小描述符数量
HAL_MAC_DMA_ALIGNIM_CACHE_MAX_LINE_SIZE_BYTES(当前 64U)描述符链与数据缓冲区要求的对齐字节数
HAL_MAC_MAX_BUFFER_SIZE2047U单个 normal 描述符缓冲区的最大字节数(对应 DES1[10:0] 位宽)
CONFIG_MAC_ENABLE_DEBUG_HELPERS默认 0U调试辅助代码开关,未配置时在头文件中补默认值

3.3 HAL 返回状态约定

HAL 可失败接口统一返回 SDK 公共错误码类型 error_code_t:

返回值说明
IM_OK操作成功
IM_ERR_INVALID_PARAM参数为空、handle 未绑定、实例非法、索引或枚举非法、配置字段越界
IM_ERR_NOT_READY状态机不允许当前操作,或单次轮询下条件未满足
IM_ERR_BUSYMDIO 忙、TX 环满且超时、或没有可回收的 TX 描述符
IM_ERR_TIMEOUT轮询等待超时(DMA 软复位、TX 环可用、RX 帧到达、MDIO 完成)
IM_ERR_UNSUPPORTED请求 enhanced 描述符、帧跨多个 RX 描述符、调试 helper 未编译
IM_ERR_NO_SPACE接收缓冲区容量小于实际帧长

HAL 不返回 IM_ERR_NO_MEMORY:描述符与缓冲区全部由调用方提供,HAL 内部不做动态分配。

3.4 公开枚举

hal_mac_speed_t / hal_mac_duplex_t:

枚举枚举值说明
hal_mac_speed_tHAL_MAC_SPEED_UNKNOWN = 0速率未知;hal_mac_set_link_config() 不接受
hal_mac_speed_tHAL_MAC_SPEED_10M = 1010 Mbps
hal_mac_speed_tHAL_MAC_SPEED_100M = 100100 Mbps
hal_mac_duplex_tHAL_MAC_DUPLEX_HALF = 0半双工
hal_mac_duplex_tHAL_MAC_DUPLEX_FULL = 1全双工
hal_mac_duplex_tHAL_MAC_DUPLEX_UNKNOWN = 2双工未知;hal_mac_set_link_config() 不接受

hal_mac_state_t:

状态说明
HAL_MAC_STATE_RESET = 0handle 尚未初始化,或已 hal_mac_deinit()
HAL_MAC_STATE_READY = 1硬件与 DMA 描述符已初始化,MAC/DMA 未启动
HAL_MAC_STATE_BUSY = 2MAC RX/TX 与 DMA RX/TX 已启动,允许收发
HAL_MAC_STATE_ERROR = 3HAL 记录了致命错误(DMA 软复位超时或 fatal bus error)

状态迁移:RESET --hal_mac_init()--> READY --hal_mac_start()--> BUSY --hal_mac_stop()--> READY;hal_mac_deinit() 从任意状态回到 RESET;DMA 软复位超时或 DMA_SR.FBI 进入 ERROR,重新 hal_mac_init() 成功后回到 READY。

约束:hal_mac_start() 只接受 READY;hal_mac_transmit()/hal_mac_receive() 只接受 BUSY;hal_mac_stop()/hal_mac_deinit() 不要求特定状态,可重复调用。

hal_mac_flow_control_t / hal_mac_desc_type_t / hal_mac_desc_mode_t:

枚举枚举值值MAC_FCR 结果/说明
hal_mac_flow_control_tHAL_MAC_FLOW_CONTROL_NONE0x0RFE=0、TFE=0
hal_mac_flow_control_tHAL_MAC_FLOW_CONTROL_RX0x1RFE=1、TFE=0
hal_mac_flow_control_tHAL_MAC_FLOW_CONTROL_TX0x2RFE=0、TFE=1
hal_mac_flow_control_tHAL_MAC_FLOW_CONTROL_RX_TX0x3RFE=1、TFE=1
hal_mac_desc_type_tHAL_MAC_DESC_NORMAL0标准 4 字(16 字节)描述符,当前唯一支持格式
hal_mac_desc_type_tHAL_MAC_DESC_ENHANCED1扩展描述符,hal_mac_init() 返回 IM_ERR_UNSUPPORTED
hal_mac_desc_mode_tHAL_MAC_DESC_MODE_RING0描述符连续排列,最后一个置 END_RING
hal_mac_desc_mode_tHAL_MAC_DESC_MODE_CHAIN1每个描述符置 CHAINED,DES3 存下一描述符地址(尾元素回绕首元素)

3.5 描述符结构与 TX/RX 位协议

typedef struct {
    uint32_t des0; /* status/control */
    uint32_t des1; /* control/buffer size */
    uint32_t des2; /* buffer 1 address */
    uint32_t des3; /* buffer 2 or next descriptor */
} hal_mac_dma_desc_t;

TX normal 描述符字段由 hal_mac.c 内部宏定义:

字位域宏含义
DES0[31]HAL_MAC_TX_DESC_OWN1 表示 DMA 拥有该描述符
DES0[30]HAL_MAC_TX_DESC_IC发送完成时请求 DMA 中断
DES0[29]HAL_MAC_TX_DESC_LS该描述符包含帧尾
DES0[28]HAL_MAC_TX_DESC_FS该描述符包含帧首
DES0[23:22]HAL_MAC_TX_DESC_CIC_SHIFT校验和插入控制;checksum_offload 时写 3(full)
DES0[21]HAL_MAC_TX_DESC_END_RING该描述符是环的最后一个元素
DES0[20]HAL_MAC_TX_DESC_CHAINEDDES3 存下一描述符地址
DES0[15]HAL_MAC_TX_DESC_ES发送错误汇总(由 DMA 写)
DES1[10:0]HAL_MAC_TX_DESC_BUFFER1_MASKbuffer1 字节长度
DES2[31:0]—buffer1 32 位地址
DES3[31:0]—CHAINED=1 时为下一描述符地址,否则保留

RX normal 描述符字段:

字位域宏含义
DES0[31]HAL_MAC_RX_DESC_OWN1 表示 DMA 拥有该描述符
DES0[29:16]HAL_MAC_RX_DESC_FL_SHIFT/MASK接收帧字节长度(14 bit)
DES0[15]HAL_MAC_RX_DESC_ES该帧的错误汇总
DES0[9]HAL_MAC_RX_DESC_FS该描述符包含帧首
DES0[8]HAL_MAC_RX_DESC_LS该描述符包含帧尾
DES1[15]HAL_MAC_RX_DESC_END_RING该描述符是环的最后一个元素
DES1[14]HAL_MAC_RX_DESC_CHAINEDDES3 存下一描述符地址
DES1[10:0]HAL_MAC_RX_DESC_BUFFER1_MASKbuffer1 字节长度
DES2[31:0]—buffer1 32 位地址
DES3[31:0]—CHAINED=1 时为下一描述符地址,否则保留

说明:HAL 每帧只用一个 TX 描述符,FS 与 LS 同时置位;CHAINED/END_RING 在初始化时按 desc_mode 写入,发送时 HAL 只保留这两位再叠加 FS|LS|IC|OWN;DES1 长度位宽 11 bit,单帧上限 2047 字节;TX 回收时保留 CHAINED|END_RING,清 DES1/DES2,保留 DES3。RX 初始化时 DES0=OWN、DES1=rx_buffer_size & 0x7FF(按 desc_mode 叠加 CHAINED/END_RING)、DES2=buffer 地址、DES3=0 或下一描述符地址;hal_mac_receive() 要求 FS 与 LS 同时置位;释放 RX 描述符给 DMA 时只把 DES0 写回 OWN,DES1/DES2/DES3 保持不变。

扩展描述符 hal_mac_dma_ext_desc_t 在 normal 描述符之后追加 des4(扩展状态/控制)、des5(保留)、des6(timestamp low)、des7(timestamp high),共 32 字节。HAL 当前拒绝 HAL_MAC_DESC_ENHANCED,hal_mac_init() 返回 IM_ERR_UNSUPPORTED;该结构体只作为未来扩展的存储定义保留。

4. 当前实现约束与行为说明

4.1 单实例、时钟与复位

G32S10 当前只暴露一个 GMAC 实例 MAC。hal_mac_handle_init() 内部直接绑定 MAC,ll_mac_is_instance() 只认该地址;不存在端口号、实例表或多句柄并发寻址。

HAL 不写 CPM 寄存器:时钟门控由 BSP 调用 hal_cpm_clk_enable(HAL_CPM_ID_GATE_MAC)/hal_cpm_clk_disable();MAC 软复位由 BSP 调用 ll_cpm_set_mac_soft_reset()/ll_cpm_clear_mac_soft_reset(),MACPHYC.SOFT_RST[3] 由 CPM 驱动管理。CONFIG_DRIVER_MAC 会 select DRIVER_CPM,但 HAL 代码本身不依赖 CPM 调用顺序。未使能时钟或 MAC 仍在复位时,hal_mac_init() 的 DMA 软复位等待会超时并返回 IM_ERR_TIMEOUT,handle 进入 ERROR 状态。

4.2 增强描述符不支持

hal_mac_dma_ext_desc_t 只是结构定义。hal_mac_init() 在 config.desc_type == HAL_MAC_DESC_ENHANCED 时返回 IM_ERR_UNSUPPORTED;hal_mac_tx_clean() 也要求 HAL_MAC_DESC_NORMAL。当前只有 normal 4 字描述符可用。

4.3 描述符与缓冲区对齐和 cache

  • 描述符数组与数据缓冲区必须按 HAL_MAC_DMA_ALIGN(IM_CACHE_MAX_LINE_SIZE_BYTES,当前 64 字节)对齐,hal_mac_config_is_valid() 会检查。

  • HAL 内部负责 cache 维护:发送前 clean TX buffer,接收前 invalidate RX buffer,描述符更新后 clean、读取前 invalidate,RX 描述符交还 DMA 前对 buffer 做 clean + invalidate。若调用方在 HAL 之外直接读写同一块 DMA buffer,需要自行处理 cache 一致性。

4.4 SoC IRQ 与 PLIC 由调用方注册

HAL 不调用 im_irq_request()、im_irq_enable()、im_irq_set_priority()。调用方需要:用 IRQ_GMAC(软件 IRQ 号 11)注册 IRQ 入口;在入口中调用 hal_mac_irq_handler(handle);根据返回的事件位图唤醒 worker thread 或做线程级处理。im_net_eth.c 是现有参考实现:start 阶段 im_irq_request(IRQ_GMAC, ...)、im_irq_set_priority()、im_irq_enable(),stop 阶段 im_irq_disable() 与 im_irq_release()。

4.5 调试 helper 双 Kconfig 条件

hal_mac_dump_regs() 与 hal_mac_dump_desc() 的日志代码受两个条件同时控制:

#if (CONFIG_SDK_ENABLE_DEBUG_HELPERS) && (CONFIG_MAC_ENABLE_DEBUG_HELPERS)

任一开关关闭时,函数直接返回 IM_ERR_UNSUPPORTED,不产生日志。

4.6 状态机与错误恢复

hal_mac_init() 失败时不会自动回滚,建议重新执行完整初始化。DMA 软复位超时与 DMA_SR.FBI 会把状态置为 ERROR,此时 hal_mac_start() 返回 IM_ERR_NOT_READY,需要重新执行 hal_mac_init()。hal_mac_stop()/hal_mac_deinit() 不清除 error_code,诊断时需注意错误位可能是历史累积值。

4.7 MACPHYC.MAC_SPEED 只读

CPM 的 MACPHYC 寄存器提供只读 MAC_SPEED[31:30](0=1000 Mbps,2=10 Mbps,3=100 Mbps,复位默认 2)、只读 MAC_PTP_PPS[0] 和 SOFT_RST[3]。HAL 不写 MACPHYC,速率/双工只通过 MAC_CR.PS/FES/DM 配置;MAC_SPEED 的实际值由板级/CPM strap 决定,HAL 不做一致性校验。

5. 典型用法

5.1 HAL 初始化与收发骨架

以下代码只使用真实头文件签名,描述初始化、启动、发送、接收和 IRQ 注册的推荐顺序。描述符与缓冲区必须静态对齐声明。该流程的可运行参考见 code/examples/hal/hal_mac_example.c(入口 example_mac_hal_selftest_run() 与 example_mac_hal_loopback_run())。

#include <string.h>

#include "hal_mac.h"
#include "hal_cpm.h"
#include "ll_cpm.h"
#include "im_irq.h"
#include "im_error.h"

#define APP_MAC_TX_DESC_COUNT  4U
#define APP_MAC_RX_DESC_COUNT  4U
#define APP_MAC_BUFFER_SIZE    1536U
#define APP_MAC_TX_TIMEOUT_MS  100U

static hal_mac_dma_desc_t s_tx_desc[APP_MAC_TX_DESC_COUNT]
    __attribute__((aligned(HAL_MAC_DMA_ALIGN)));
static hal_mac_dma_desc_t s_rx_desc[APP_MAC_RX_DESC_COUNT]
    __attribute__((aligned(HAL_MAC_DMA_ALIGN)));
static uint8_t s_tx_buffer[APP_MAC_TX_DESC_COUNT * APP_MAC_BUFFER_SIZE]
    __attribute__((aligned(HAL_MAC_DMA_ALIGN)));
static uint8_t s_rx_buffer[APP_MAC_RX_DESC_COUNT * APP_MAC_BUFFER_SIZE]
    __attribute__((aligned(HAL_MAC_DMA_ALIGN)));

static hal_mac_handle_t s_mac_handle;

static void app_mac_irq_handler(uint32_t irq_id, void *arg);

error_code_t app_mac_init(const uint8_t mac_address[HAL_MAC_ADDRESS_SIZE])
{
    error_code_t ret;

    /* 1. Board/CPM: enable MAC clock and release MAC soft reset. */
    ret = hal_cpm_clk_enable(HAL_CPM_ID_GATE_MAC);
    if (ret != IM_OK) {
        return ret;
    }
    ll_cpm_set_mac_soft_reset();
    ll_cpm_clear_mac_soft_reset();

    /* 2. Bind the single MAC instance; config must be filled after it. */
    ret = hal_mac_handle_init(&s_mac_handle);
    if (ret != IM_OK) {
        return ret;
    }

    memcpy(s_mac_handle.config.mac_address, mac_address, HAL_MAC_ADDRESS_SIZE);
    s_mac_handle.config.mtu = HAL_MAC_DEFAULT_MTU;
    s_mac_handle.config.speed = HAL_MAC_SPEED_100M;
    s_mac_handle.config.duplex = HAL_MAC_DUPLEX_FULL;
    s_mac_handle.config.mdc_clock_range = 0U;
    s_mac_handle.config.tx_dma_pbl = 8U;
    s_mac_handle.config.rx_dma_pbl = 8U;
    s_mac_handle.config.desc_type = HAL_MAC_DESC_NORMAL;
    s_mac_handle.config.desc_mode = HAL_MAC_DESC_MODE_RING;
    s_mac_handle.config.tx_desc = s_tx_desc;
    s_mac_handle.config.rx_desc = s_rx_desc;
    s_mac_handle.config.tx_desc_count = APP_MAC_TX_DESC_COUNT;
    s_mac_handle.config.rx_desc_count = APP_MAC_RX_DESC_COUNT;
    s_mac_handle.config.tx_buffer = s_tx_buffer;
    s_mac_handle.config.rx_buffer = s_rx_buffer;
    s_mac_handle.config.tx_buffer_size = APP_MAC_BUFFER_SIZE;
    s_mac_handle.config.rx_buffer_size = APP_MAC_BUFFER_SIZE;

    if (!hal_mac_config_is_valid(&s_mac_handle.config)) {
        return IM_ERR_INVALID_PARAM;
    }

    /* 3. Program DMA/descriptors/MAC core; state becomes READY. */
    ret = hal_mac_init(&s_mac_handle);
    if (ret != IM_OK) {
        return ret;
    }

    /* 4. Register SoC IRQ; the handler only records events. */
    ret = im_irq_request((uint32_t)IRQ_GMAC, app_mac_irq_handler,
                         "app_mac", &s_mac_handle);
    if (ret != IM_OK) {
        (void)hal_mac_deinit(&s_mac_handle);
        return ret;
    }
    ret = im_irq_enable((uint32_t)IRQ_GMAC);
    if (ret != IM_OK) {
        (void)im_irq_release((uint32_t)IRQ_GMAC);
        (void)hal_mac_deinit(&s_mac_handle);
        return ret;
    }

    /* 5. Start MAC RX/TX and DMA; state becomes BUSY. */
    return hal_mac_start(&s_mac_handle);
}

IRQ 入口只做状态处理与事件记录,不拷贝帧、不回收描述符:

static void app_mac_irq_handler(uint32_t irq_id, void *arg)
{
    hal_mac_handle_t *handle = (hal_mac_handle_t *)arg;
    uint32_t events;

    (void)irq_id;
    events = hal_mac_irq_handler(handle);

    /*
     * Record events and wake the application worker thread.
     * The worker calls hal_mac_tx_reclaim() after HAL_MAC_EVENT_TX and
     * hal_mac_receive() after HAL_MAC_EVENT_RX, in thread context.
     */
    (void)events;
}

线程上下文的发送、回收与接收:

ret = hal_mac_transmit(&s_mac_handle, frame, frame_len, APP_MAC_TX_TIMEOUT_MS);
(void)hal_mac_tx_reclaim(&s_mac_handle); /* thread context, after HAL_MAC_EVENT_TX */

rx_len = sizeof(rx_frame);
ret = hal_mac_receive(&s_mac_handle, rx_frame, &rx_len, 0U); /* 0: single poll */

说明:hal_mac_tx_reclaim() 按头文件约定在线程上下文调用,IRQ 中不回收描述符;hal_mac_receive() 使用 timeout_ms = 0 时只检查一次,适合在 worker thread 中循环 drain,直到返回非 IM_OK。结束流程:im_irq_disable(IRQ_GMAC) → im_irq_release(IRQ_GMAC) → hal_mac_stop() → hal_mac_deinit(),最后按板级需要关闭 CPM 时钟。

5.2 LL 寄存器自测示例

参考实现:code/examples/ll/mac_ll_example.c,入口为:

error_code_t example_mac_ll_selftest_run(void);
error_code_t example_mac_ll_loopback_run(void);

example_mac_ll_selftest_run() 的返回语义:全部检查通过返回 IM_OK;实例不是 MAC 返回 IM_ERR_INVALID_PARAM;CPM 时钟使能失败原样透传;任一寄存器回读不符返回 IM_ERR_NOT_READY;MDIO 无 PHY 或超时只告警,不影响返回值。

行为概述:

阶段内容
1校验 ll_mac_is_instance(MAC);使能 HAL_CPM_ID_GATE_MAC,CPM MAC 软复位(set → im_time_delay_ms(1) → clear → im_time_delay_ms(1));寄存器测试开始前先停止 DMA
2保存 CR、FFR、FCR、IMR、A0HR/A0LR、A1HR/A1LR、DMA_BMR、DMA_RDLAR/TDLAR、DMA_OMR、DMA_IER 快照;VR/HWFR 只记录(非全 0/全 F 仅告警)
3CR set/clear 回读、FFR set/clear、FCR(PT + RFE/TFE)、IMR 整寄存器读写
4A0:写 ADDRHI 后回读,并确认 ll_mac_set_address0_high() 保留 AE;A1:ll_mac_set_address1_high() 整寄存器写入 AE/SA/MBC/ADDRHI 后回读,再写 A1LR
5DMA_BMR(PBL=8、RPBL=8,确认 SWR 未置位)、DMA_RDLAR/TDLAR(64 字节对齐静态描述符数组的 32 位地址)、DMA_OMR(TSF|RSF|OSF,确认 ST/SR=0)、DMA_IER(NORMAL/ABNORMAL)
6DMA_SR 读→写 MAC_DMA_SR_CLEARABLE_MASK→再读;读取 DMA_MFOCR 观察读清;触发 ll_mac_dma_poll_tx()/poll_rx();读取 CHTDR/CHRDR/CHTBAR/CHRBAR/AHBSR 仅记录
7MDIO 探测:等 GMII_AR.GB 清零后读 PHY 地址 0 的 ID1/ID2(超时只告警);随后恢复快照、停止 DMA、关闭时钟,全部通过时打印通过日志

说明:自测只使用 ll_mac.h 与 CPM 时钟/复位接口,不经过 HAL MAC,也不注册 SoC IRQ;快照在 CPM 软复位之后采集,恢复后 MAC 回到复位后状态而不是进入示例前的状态。

5.3 LL 内部 loopback 数据通路示例

example_mac_ll_loopback_run() 通过 MAC_CR.LM 打开 MAC 内部 loopback,用最小描述符环验证 TX→RX 数据通路。返回 IM_OK 表示帧回环与载荷校验通过;IM_ERR_TIMEOUT 表示 DMA 软复位/TX 完成/RX 完成超时;IM_ERR_HARDWARE 表示 TX 描述符 ES;IM_ERR_NOT_READY 表示 RX ES、FS/LS 不完整、长度非 64/68 或载荷不符;实例非法返回 IM_ERR_INVALID_PARAM;时钟失败原样透传。

行为概述:

阶段内容
1使能 MAC 时钟、CPM MAC 软复位(set → delay 1 ms → clear → delay 1 ms)并保存快照
2DMA 软复位;写 A0 单播地址;MAC_FFR=0(只保留 A0 单播过滤)
3配置 2 个 TX + 2 个 RX 描述符(64 字节对齐静态数组,RX 末项置 END_RING、TX 末项仅置 END_RING);1 个 1536 字节 TX buffer + 1 个 1536 字节 RX buffer,两个 RX 描述符指向同一 RX buffer
4MAC_CR 置 PS | DM | LM | TE | RE | ACS | CST;DMA_BMR 写 PBL/RPBL=8;写 DMA_RDLAR/TDLAR;DMA_OMR=TSF | RSF | OSF;DMA_IER=0;清 DMA_SR 后置 ST | SR
5构造 64 字节帧(DA=A0 地址、SA=02:00:00:00:00:02、类型 0x88B5、模式载荷)写入 TX buffer 并 clean;写 TX 描述符 OWN|FS|LS、DES1=64、DES2=32 位 buffer 地址,clean 后 poll_tx;轮询 TX OWN 清零或 DMA_SR.TI(超时 EXAMPLE_MAC_TIMEOUT_MS=100),检查 TX ES
6清 TX 状态后 poll_rx,轮询 RX 描述符 OWN 清零;检查 RX ES、FS|LS、DES0[29:16] 长度为 64 或 68(FCS 残留 4 字节),invalidate RX buffer 后校验前 64 字节载荷
7停 DMA(清 ST|SR)、DMA_IER=0、清 CR.TE|RE|LM、清 DMA_SR;恢复快照、关闭时钟

板级前提:

  • MAC 时钟门控与 MAC 软复位由 BSP/CPM 负责;loopback 前额外执行一次 DMA 软复位。

  • 内部 loopback 仍需 MII TX 时钟,通常由外部 PHY 提供;没有 TX 时钟时发送不会推进并超时。

  • MAC_CR.FES 保持板级复位值,因此 MII TX 时钟必须与默认 link speed 匹配;pinmux、PHY 复位、link 配置由 BSP 负责。

  • 示例不注册/不使能任何 SoC 中断,DMA 完成全部通过状态位与描述符轮询。

内部 loopback 依赖 MAC_CR.PS 选择 MII 模式;LM 置位后发送帧在 MAC 内部回送到接收路径,不经过外部 PHY 的线缆侧。

5.4 生产参考

参考说明
code/middleware/net/net_adapter/ethernet/im_net_eth.c现有生产接入:HAL MAC + PHY + lwIP netif、worker thread、IRQ 注册与 RX drain
code/examples/hal/hal_mac_example.cHAL MAC bring-up 自测与内部 loopback 收发示例(8.1 流程的可运行版本,轮询方式,不注册 IRQ)
docs/api/g32s10/middleware/mac_mid_api.mdMAC MID 与 PHY/lwIP 接入、初始化流程、数据流、调试命令与约束
code/examples/ll/mac_ll_example.c本文档 8.2/8.3 对应的 LL 自测与 loopback 示例
test/g32s10/module/gmac/GMAC 模块级测试(寄存器、basic、MTU、中断、压力、健壮性)

6. 推荐关注的错误码

API/场景推荐关注错误码说明
hal_mac_handle_init() / hal_mac_config_is_valid()IM_ERR_INVALID_PARAM / falsehandle 为空、实例检查失败,或配置字段越界、指针为空、未按 64 字节对齐
hal_mac_init()IM_ERR_INVALID_PARAM未先 hal_mac_handle_init()、未填 config 或 config 非法
hal_mac_init()IM_ERR_UNSUPPORTED请求 enhanced 描述符
hal_mac_init()IM_ERR_TIMEOUTCPM 时钟未使能或 MAC 仍在复位,DMA 软复位无法完成
hal_mac_start()IM_ERR_NOT_READY尚未初始化、已启动或处于 ERROR
hal_mac_transmit()IM_ERR_INVALID_PARAMdata 为空、len 为 0 或超过 tx_buffer_size
hal_mac_transmit()IM_ERR_NOT_READY未 hal_mac_start(),或 systick 未初始化且 timeout_ms > 0
hal_mac_transmit()IM_ERR_TIMEOUTTX 环长时间无可用描述符
hal_mac_receive()IM_ERR_TIMEOUT当前无新帧(timeout_ms = 0 时常见)
hal_mac_receive()IM_ERR_NOT_READY / IM_ERR_UNSUPPORTED未启动、丢弃错误帧,或帧跨多个 RX 描述符
hal_mac_receive()IM_ERR_NO_SPACE目的缓冲区不足,*len_inout 返回所需长度
hal_mac_tx_reclaim()IM_ERR_BUSY / IM_ERR_UNSUPPORTED暂无完成描述符 / 描述符类型不是 normal
hal_mac_mdio_read() / hal_mac_mdio_write()IM_ERR_BUSYMDIO 上一次事务尚未完成
hal_mac_mdio_read() / hal_mac_mdio_write()IM_ERR_TIMEOUTMDIO 事务超时或 systick 未初始化
hal_mac_set_link_config()IM_ERR_INVALID_PARAMspeed/duplex 传 UNKNOWN 或越界值
hal_mac_set_flow_control()IM_ERR_INVALID_PARAMflow_control 含 RX_TX 之外的位
hal_mac_set_address()IM_ERR_INVALID_PARAMindex 不是 0/1
hal_mac_dump_regs() / hal_mac_dump_desc()IM_ERR_UNSUPPORTED / IM_ERR_NOT_READY调试 helper 未同时使能两个 Kconfig 开关 / 描述符数量为 0
LL 调用无错误码LL 返回 void/寄存器值,参数与状态由调用方保证