API GUIDE / MAC / HAL

G32S10 MAC HAL 接口

HAL 层接口:hal_mac.h 为调试开关提供默认值,保证未经过 Kconfig 时也可编译:

1. 资源模型与公开类型

1.1 Kconfig 选项

配置项类型/依赖默认值说明
CONFIG_DRIVER_MACbool,select DRIVER_CPMn编译 G32S10 MAC HAL 驱动
CONFIG_MAC_ENABLE_DEBUG_HELPERSbool,depends on SDK_ENABLE_DEBUG_HELPERSn编译 MAC 调试辅助代码(寄存器/描述符 dump)
CONFIG_SDK_ENABLE_DEBUG_HELPERSSDK 全局开关由 SDK 配置决定与上一项同时打开时 dump 接口才输出日志

hal_mac.h 为调试开关提供默认值,保证未经过 Kconfig 时也可编译:

#ifndef CONFIG_MAC_ENABLE_DEBUG_HELPERS
#define CONFIG_MAC_ENABLE_DEBUG_HELPERS  (0U)
#endif

CMakeLists.txt 在 CONFIG_DRIVER_MAC 打开时注册组件 g32s10_mac,源文件为 hal_mac.c。

1.2 硬件能力摘要

以下能力均可由 mac_regs.h、hal_mac.h 或 hal_mac.c 直接证实;未封装的硬件特性单独标注。

项目说明依据
控制器实例单实例 MACmac_regs.h
速率与双工MAC_CR.PS 选择 MII、FES 选择 10/100 Mbps、DM 选择半/全双工;HAL 只接受 10M/100Mhal_mac_speed_t、hal_mac_duplex_t
MDIOIEEE 802.3 Clause 22,PHY 地址与寄存器地址各 5 bit,MDC 时钟范围 4 bitGMII_AR.PA[15:11]、GR[10:6]、CR[5:2]
DMA 描述符normal 4 字描述符;enhanced 有结构定义但 HAL 当前拒绝hal_mac_dma_desc_t、hal_mac_dma_ext_desc_t、hal_mac_init()
DMA 突发TX/RX PBL 可配,取值 1/2/4/8/16/32;支持 fixed burst、mixed bursthal_mac_config_t、MAC_DMA_BMR.PBL/RPBL/FB/MB
DMA 地址宽度描述符基地址与 buffer 地址按 32 位编程hal_mac.c 中 (uint32_t)(uintptr_t) 转换
MAC 地址寄存器2 个(索引 0、1)MAC_ADDRESS_REGISTER_COUNT
流控与校验和MAC_FCR.RFE/TFE 与 pause time;RX MAC_CR.IPC;TX descriptor CIC=3hal_mac_set_flow_control()、hal_mac_config_t
中断单个 SoC IRQ IRQ_GMAC;DMA 数据通路中断经 DMA_IER 使能;MAC_ISR 的 LPI/TS/PMT/PCS/RGSMII 等 MAC 核中断由 MAC_IMR 屏蔽(MMC 中断位无对应 IMR mask),HAL 均不处理irq_table.def、hal_mac_init()、MAC_ISR_*
时间戳/PPS/AV/MMC/LPI/VLAN寄存器布局与位域有定义,HAL/LL 未提供访问函数mac_regs.h、MAC_LPI_*、MAC_VTR_*

1.3 错误位

错误位值置位来源
HAL_MAC_ERROR_NONE0x000初始值
HAL_MAC_ERROR_INVALID_PARAM0x001定义保留;当前实现不在 handle 中置位
HAL_MAC_ERROR_DMA_RESET_TIMEOUT0x002hal_mac_init() 等待 DMA_BMR.SWR 清零超时
HAL_MAC_ERROR_TX_TIMEOUT0x004hal_mac_transmit() 等待 TX 环可用超时,或 systick 未初始化
HAL_MAC_ERROR_RX_TIMEOUT0x008定义保留;当前 hal_mac_receive() 超时只返回错误码,不置位
HAL_MAC_ERROR_MII_TIMEOUT0x010MDIO 等待 GMII_AR.GB 清零超时
HAL_MAC_ERROR_TX_UNDERFLOW0x020hal_mac_irq_handler() 处理 DMA_SR.UNF
HAL_MAC_ERROR_RX_OVERFLOW0x040hal_mac_irq_handler() 处理 DMA_SR.OVF
HAL_MAC_ERROR_FATAL_BUS0x080hal_mac_irq_handler() 处理 DMA_SR.FBI,同时进入 ERROR 状态
HAL_MAC_ERROR_RX_FRAME0x100hal_mac_receive() 丢弃错误帧/分段帧

handle->error_code 是错误位的 OR 累积值,只有 hal_mac_handle_init()/hal_mac_init() 会清零。致命错误只有 DMA_RESET_TIMEOUT 与 FATAL_BUS,都会把状态置为 ERROR。

1.4 事件位

事件位值对应 DMA_SR 位说明
HAL_MAC_EVENT_NONE0x00无无事件
HAL_MAC_EVENT_RX0x01RI[6]RX 帧完成
HAL_MAC_EVENT_TX0x02TI[0]TX 帧完成
HAL_MAC_EVENT_RX_BUFFER_UNAVAILABLE0x04RU[7]RX 缓冲区不可用
HAL_MAC_EVENT_TX_BUFFER_UNAVAILABLE0x08TU[2]TX 缓冲区不可用
HAL_MAC_EVENT_TX_UNDERFLOW0x10UNF[5]TX underflow
HAL_MAC_EVENT_RX_OVERFLOW0x20OVF[4]RX overflow
HAL_MAC_EVENT_FATAL_BUS_ERROR0x40FBI[13]致命总线错误
HAL_MAC_EVENT_ABNORMAL0x80AIS[15]DMA 异常中断汇总

说明:事件集合只覆盖 HAL 默认通过 DMA_IER 使能的 DMA 数据通路中断源。DMA_SR 中 early receive/transmit、receive watchdog、process-stopped、jabber timeout 等源当前未使能,不会由 hal_mac_irq_handler() 报告;MAC_ISR 中的 LPI、PMT、PCS、MMC、timestamp 等 MAC 核中断源不在该 handler 范围内。

1.5 hal_mac_config_t

字段类型说明约束
mac_addressuint8_t[6]主 MAC 地址,hal_mac_init() 写入地址寄存器 06 字节;字节序见 4.3.3
mtuuint32_tEthernet MTU> 0 且 <= HAL_MAC_MAX_MTU(2000);> 1500 时 HAL 置 MAC_CR.TWOKPE
speedhal_mac_speed_t初始速率HAL_MAC_SPEED_10M 或 HAL_MAC_SPEED_100M
duplexhal_mac_duplex_t初始双工HAL_MAC_DUPLEX_HALF 或 HAL_MAC_DUPLEX_FULL
mdc_clock_rangeuint32_tGMII_AR.CR[5:2] 字段值0 ~ 0xF
tx_dma_pbl / rx_dma_pbluint32_t分别写入 DMA_BMR.PBL / RPBL 的 TX/RX 突发长度非 0、<= 32 且为 2 的幂(1/2/4/8/16/32)
fixed_burst / mixed_burstbool置 DMA_BMR.FB / MB无额外校验;两者互斥性由调用方保证
checksum_offloadbool置 MAC_CR.IPC,并在 TX 描述符写 CIC=3无额外校验
rx_watchdog_enablebool为真时写 DMA_RIWTR无额外校验
rx_watchdoguint8_tDMA_RIWTR.RIWT[7:0] 值0 ~ 0xFF
desc_typehal_mac_desc_type_t描述符格式hal_mac_config_is_valid() 接受两个枚举值,但 hal_mac_init() 只接受 HAL_MAC_DESC_NORMAL
desc_modehal_mac_desc_mode_t描述符遍历方式RING 或 CHAIN
tx_desc / rx_descvoid *TX/RX 描述符数组首地址非 NULL,按 HAL_MAC_DMA_ALIGN 对齐,容量至少 count * sizeof(hal_mac_dma_desc_t)
tx_desc_count / rx_desc_countuint32_tTX/RX 描述符数量>= HAL_MAC_MIN_DESCRIPTOR_COUNT(2)
tx_buffer / rx_bufferuint8_t *TX/RX 缓冲区首地址非 NULL,按 HAL_MAC_DMA_ALIGN 对齐,容量至少 count * buffer_size
tx_buffer_size / rx_buffer_sizeuint32_t每个 TX/RX 槽字节数>= mtu 且 <= HAL_MAC_MAX_BUFFER_SIZE(2047)

hal_mac_config_is_valid() 会逐项校验上表约束。hal_mac_handle_init() 会清零整个 handle,因此必须在 hal_mac_handle_init() 之后再填充 handle->config。

1.6 hal_mac_stats_t

字段说明更新点
tx_packetsDMA 完成且描述符无错误的 TX 帧数hal_mac_tx_clean()
rx_packets成功接收并拷贝的 RX 帧数hal_mac_receive()
tx_bytes拷入 TX 缓冲区的字节数(按完成描述符长度统计)hal_mac_tx_clean()
rx_bytes从 RX 缓冲区拷出的字节数(FCS 处理后)hal_mac_receive()
tx_errorsTX 侧 HAL 错误计数(描述符 ES、TX underflow)hal_mac_tx_clean()、hal_mac_irq_handler()
rx_errorsRX 侧 HAL 错误计数(丢弃错误帧、RX overflow)hal_mac_receive()、hal_mac_irq_handler()
tx_underflow_errorsDMA UNF 次数hal_mac_irq_handler()
rx_overflow_errorsDMA OVF 次数hal_mac_irq_handler()
fatal_bus_errorsDMA FBI 次数hal_mac_irq_handler()

统计只在 hal_mac_handle_init()/hal_mac_init() 时清零,其余时刻单调累加。

1.7 hal_mac_handle_t

字段类型说明
macxmac_regs_t *绑定的 MAC 寄存器块,当前固定为 MAC
confighal_mac_config_t初始化配置副本;hal_mac_set_link_config() 会回写 speed/duplex
statehal_mac_state_t当前 HAL 状态
error_codeuint32_tOR 累积的 hal_mac_error_t 错误位
tx_indexuint32_t下一次 hal_mac_transmit() 使用的 TX 描述符索引
tx_clean_indexuint32_t下一次回收检查的 TX 描述符索引
tx_pending_countuint32_t已交给 DMA、尚未回收的 TX 描述符数量
rx_indexuint32_t下一次 hal_mac_receive() 使用的 RX 描述符索引
statshal_mac_stats_t运行期统计

说明:HAL 不提供内部锁。hal_mac_transmit() 与 hal_mac_tx_reclaim() 内部用短临界区保护 TX 环索引与描述符状态,但 config、stats、state、error_code 的并发访问仍需调用方串行化;同一 handle 不应被多个任务或任务与 ISR 同时操作。

2. HAL 接口规范

HAL 公开函数共 19 个,分为生命周期与状态、数据路径、链路与 MDIO、查询与调试四组。

2.1 生命周期与状态

2.1.1 hal_mac_config_is_valid

bool hal_mac_config_is_valid(const hal_mac_config_t *config);

功能:校验配置负载是否满足 HAL 的硬件与内存约束,不做任何寄存器操作。参数 config 为待校验配置,NULL 返回 false。

返回:true 合法,false 非法。校验项包括:speed/duplex/desc_type/desc_mode 枚举合法;mtu 为 1 ~ HAL_MAC_MAX_MTU;mdc_clock_range <= 0xF;PBL 非 0、<= 32 且为 2 的幂;四个指针非 NULL 且按 HAL_MAC_DMA_ALIGN 对齐;tx_desc_count/rx_desc_count >= HAL_MAC_MIN_DESCRIPTOR_COUNT;tx_buffer_size/rx_buffer_size 均在 [mtu, HAL_MAC_MAX_BUFFER_SIZE] 内。注意本函数接受 HAL_MAC_DESC_ENHANCED,但 hal_mac_init() 会拒绝。

2.1.2 hal_mac_handle_init

error_code_t hal_mac_handle_init(hal_mac_handle_t *handle);

功能:清零 handle,绑定默认 MAC 实例,状态置 HAL_MAC_STATE_RESET;不访问 MAC 寄存器、不使能时钟。参数 handle 为调用方提供的存储,为空或 MAC 实例检查失败返回 IM_ERR_INVALID_PARAM。

返回:IM_OK 或 IM_ERR_INVALID_PARAM。本函数会 memset 整个 handle,因此 handle->config 必须在调用本函数之后填充。典型顺序:hal_mac_handle_init() → 填充 handle->config → hal_mac_init()。

2.1.3 hal_mac_init

error_code_t hal_mac_init(hal_mac_handle_t *handle);

功能:复位 DMA、初始化 TX/RX 描述符环、编程 DMA 与 MAC 基础寄存器,使 handle 进入 READY;MAC RX/TX 与 DMA 引擎仍保持停止,需要 hal_mac_start() 才启动。参数 handle 必须已完成 hal_mac_handle_init() 并填充 config。

返回值说明
IM_OK初始化成功,状态为 READY
IM_ERR_INVALID_PARAMhandle 为空、实例非法或 config 未通过 hal_mac_config_is_valid()
IM_ERR_UNSUPPORTEDconfig.desc_type == HAL_MAC_DESC_ENHANCED
IM_ERR_TIMEOUT等待 DMA_BMR.SWR 清零超过内部 100 ms 超时

执行步骤:

  1. 清零 state、error_code、TX/RX 索引与计数、stats,状态置 RESET。

  2. 置 DMA_BMR.SWR 发起 DMA 软复位,等待其自动清零(HAL_MAC_DMA_RESET_TIMEOUT_MS = 100)。

  3. 按 desc_mode 初始化描述符:RING 在尾元素置 END_RING,CHAIN 在所有元素置 CHAINED 并写下一元素地址(尾元素回绕首元素);随后写 DMA_TDLAR/DMA_RDLAR 为 32 位基地址。

  4. 编程 DMA_BMR(PBL、RPBL,按需 FB、MB)、DMA_OMR = TSF|RSF|OSF、DMA_IER = NORMAL_IRQ_MASK|ABNORMAL_IRQ_MASK(NIE|RIE|TIE|AIE|FBE|UNE),按需写 DMA_RIWTR。

  5. 写入地址寄存器 0;再执行 MAC 核配置:MAC_CR |= JD|PS|ACS|BE,MTU 大于 1500 时追加 TWOKPE,checksum_offload 时追加 IPC;随后写速率/双工位;最后写 MAC_IMR 屏蔽 LPIIM|TSIM|PMTIM|PCSANCIM|PCSLCHGIM|RGSMIIIM。

  6. 状态置 READY,返回 IM_OK。

补充说明:时钟门控与 MAC 软复位不由本接口负责;调用前 BSP 必须已使能 HAL_CPM_ID_GATE_MAC 并释放 MAC 软复位。描述符与 DMA 寄存器编程可重复;失败时不会回滚已写寄存器,建议重新走完整初始化流程;DMA 软复位超时会置 ERROR 状态。

2.1.4 hal_mac_deinit

error_code_t hal_mac_deinit(hal_mac_handle_t *handle);

功能:停止 MAC RX/TX 与 DMA,清 DMA_IER,handle 状态置回 RESET。参数 handle 为已初始化句柄;返回 IM_OK,handle 为空或实例非法返回 IM_ERR_INVALID_PARAM。

补充说明:内部调用 hal_mac_stop(),可重复调用;不关闭 CPM 时钟、不置 MAC 软复位、不释放描述符/缓冲区内存,也不清零 stats 与 error_code。

2.1.5 hal_mac_start

error_code_t hal_mac_start(hal_mac_handle_t *handle);

功能:置 MAC_CR.TE|RE 使能 MAC 发送/接收,置 DMA_OMR.ST|SR 启动 DMA TX/RX 引擎,状态变为 BUSY。

返回值说明
IM_OK启动成功,状态为 BUSY
IM_ERR_INVALID_PARAMhandle 为空或实例非法
IM_ERR_NOT_READY当前状态不是 HAL_MAC_STATE_READY

补充说明:只置启动位,不重写描述符或配置寄存器;重复调用会因状态不是 READY 而返回 IM_ERR_NOT_READY。

2.1.6 hal_mac_stop

error_code_t hal_mac_stop(hal_mac_handle_t *handle);

功能:清 DMA_OMR.ST|SR 与 MAC_CR.TE|RE,停止 MAC/DMA 收发。返回 IM_OK;handle 为空或实例非法返回 IM_ERR_INVALID_PARAM。

补充说明:不检查当前状态;状态为 BUSY 时停止后变为 READY,其它状态不变。停止后未回收的 TX 描述符与未读取的 RX 描述符不会被清除,重新 hal_mac_start() 后可继续处理。

2.2 数据路径

2.2.1 hal_mac_transmit

error_code_t hal_mac_transmit(hal_mac_handle_t *handle,
                              const uint8_t *data,
                              uint32_t len,
                              uint32_t timeout_ms);

功能:把一帧数据拷入 TX 缓冲区,填写当前 TX 描述符并交给 DMA。参数 handle 必须处于 BUSY;data 为帧数据首地址;len 必须 > 0 且 <= config.tx_buffer_size;timeout_ms 为等待 TX 环可用的超时,0 表示只检查一次。

返回值说明
IM_OK帧已交给 DMA
IM_ERR_INVALID_PARAMhandle/实例/data 非法,或 len 越界
IM_ERR_NOT_READY状态不是 BUSY;或 timeout_ms > 0 且 systick 未初始化
IM_ERR_TIMEOUT超时时间内没有等到可用 TX 描述符

行为与约束:

  • 进入短临界区后先调用内部 hal_mac_tx_clean() 回收已完成描述符;tx_pending_count >= tx_desc_count 时释放临界区并按 timeout_ms 重试。当前 tx_index 描述符若仍被 DMA 拥有(DES0[31]=1),说明环满,需要等待。

  • timeout_ms == 0 时只检查一次,条件不满足立即失败;timeout_ms > 0 时循环等待,内部每轮 msleep(1)。等待依赖 im_systick_is_initialized();未初始化 systick 且 timeout_ms > 0 时记录 HAL_MAC_ERROR_TX_TIMEOUT 并返回 IM_ERR_NOT_READY。

  • 数据拷入 config.tx_buffer[tx_index * tx_buffer_size] 后对缓冲区做 cache clean。

  • 成功后推进 tx_index 并递增 tx_pending_count,一帧只占一个描述符。本接口不做链路状态检查;链路 down 时是否发送由上层决定。

2.2.2 hal_mac_receive

error_code_t hal_mac_receive(hal_mac_handle_t *handle,
                             uint8_t *data,
                             uint32_t *len_inout,
                             uint32_t timeout_ms);

功能:从当前 RX 描述符读取一帧,做 FCS 处理与基本合法性检查后拷出。参数 handle 必须处于 BUSY;data 为目的缓冲区;len_inout 输入为容量、输出为实际帧长(FCS 处理后);timeout_ms 为等待 RX 帧的超时,0 表示只检查一次。

返回值说明
IM_OK成功接收一帧
IM_ERR_INVALID_PARAMhandle/实例/data/len_inout 非法,或 *len_inout == 0
IM_ERR_NOT_READY状态不是 BUSY;发生错误帧丢弃;或 systick 未初始化且 timeout_ms > 0
IM_ERR_TIMEOUT超时时间内当前 RX 描述符仍被 DMA 拥有
IM_ERR_UNSUPPORTED帧没有同时置 FS 与 LS(跨描述符帧),该帧被丢弃
IM_ERR_NO_SPACE目的缓冲区容量小于实际帧长;*len_inout 被更新为所需长度,该帧被丢弃

行为与约束:

  • 每次调用首先读取 DMA_MFOCR(读清寄存器),该读取会清除 missed frame 计数与 overflow 标志,只用于调试日志,不影响接收流程。

  • 当前 rx_index 描述符被 DMA 拥有(DES0[31]=1)时按 timeout_ms 等待;timeout_ms == 0 只检查一次。DES0[15](错误汇总)置位时丢弃该帧:rx_errors++、置 HAL_MAC_ERROR_RX_FRAME、释放描述符,返回 IM_ERR_NOT_READY;帧未同时置 FS 与 LS 时丢弃并返回 IM_ERR_UNSUPPORTED。

  • 帧长取自 DES0[29:16],随后按 FCS 规则修正:

类型/长度字段MAC_CR 条件HAL 判定
< 0x0600(802.3 长度字段)ACS = 1硬件已剥离 FCS,不再减 4
>= 0x0600(EtherType)CST = 1硬件已剥离 FCS,不再减 4
其它情况—认为 FCS 仍在帧尾,HAL 去掉末尾 4 字节
  • FCS 处理后帧长仍小于 Ethernet 头(14 字节)时丢弃;需要减 FCS 但帧长不足 4 字节时也丢弃。目的缓冲区不足时先写回所需长度,再丢弃该帧并返回 IM_ERR_NO_SPACE。

2.2.3 hal_mac_tx_reclaim

error_code_t hal_mac_tx_reclaim(hal_mac_handle_t *handle);

功能:回收已由 DMA 完成的 TX 描述符,更新 TX 统计和索引。参数 handle 为已初始化句柄。

返回值说明
IM_OK至少回收一个描述符
IM_ERR_BUSY当前没有已完成的 TX 描述符
IM_ERR_INVALID_PARAMhandle 为空或实例非法
IM_ERR_UNSUPPORTEDconfig.desc_type != HAL_MAC_DESC_NORMAL

补充说明:

  • 头文件约定本接口在线程上下文调用,不要在中断上下文中调用;实现内部用短临界区保护 TX 环。典型时机:收到 HAL_MAC_EVENT_TX 之后,或在检查 TX 环空间之前。

  • 回收逻辑从 tx_clean_index 开始逐项 invalidate 描述符;OWN 仍为 1 时停止。对 LS 置位的描述符统计:ES 置位时 tx_errors++,否则 tx_packets++ 且 tx_bytes += DES1[10:0]。

  • 回收后描述符 DES0 只保留 CHAINED|END_RING,DES1、DES2 清零,DES3 保留。

2.2.4 hal_mac_irq_handler

uint32_t hal_mac_irq_handler(hal_mac_handle_t *handle);

功能:读取并清除 HAL 已处理的 DMA 数据通路中断状态,返回事件位图供上层分发。参数 handle 为 MAC handle,为 NULL 或实例非法时直接返回 0;返回 OR 组合的 hal_mac_event_t 位图,无事件时返回 HAL_MAC_EVENT_NONE。

DMA_SR 位与事件、副作用的对应关系:

DMA_SR 位事件附加动作
RI[6]HAL_MAC_EVENT_RX无
TI[0]HAL_MAC_EVENT_TX无
RU[7]HAL_MAC_EVENT_RX_BUFFER_UNAVAILABLE无
TU[2]HAL_MAC_EVENT_TX_BUFFER_UNAVAILABLE无
UNF[5]HAL_MAC_EVENT_TX_UNDERFLOWtx_underflow_errors++、tx_errors++、置 HAL_MAC_ERROR_TX_UNDERFLOW
OVF[4]HAL_MAC_EVENT_RX_OVERFLOWrx_overflow_errors++、rx_errors++、置 HAL_MAC_ERROR_RX_OVERFLOW
FBI[13]HAL_MAC_EVENT_FATAL_BUS_ERRORfatal_bus_errors++、置 HAL_MAC_ERROR_FATAL_BUS 并进入 ERROR 状态
AIS[15]HAL_MAC_EVENT_ABNORMAL无
NIS[16]无对应事件仅清除状态位

补充说明:

  • 只清除上述已处理的 DMA_SR 位与 NIS,未处理的中断源(early RX/TX、RWT、RPS、ETI、ERI 等)不清除;本 handler 也不读取 MAC_ISR,不处理 LPI、PMT、PCS、MMC、timestamp 等 MAC 核中断(这些源在 hal_mac_init() 中通过 MAC_IMR 屏蔽)。

  • 本 handler 不回收 TX 描述符。收到 HAL_MAC_EVENT_TX 后,调用方应在线程上下文调用 hal_mac_tx_reclaim()。

  • 调用方应在 SoC IRQ 入口调用本接口,并把返回值交给事件/worker 分发逻辑;不要在 IRQ 中做帧拷贝或阻塞等待。

2.3 链路、MDIO 与地址

2.3.1 hal_mac_mdio_read

error_code_t hal_mac_mdio_read(hal_mac_handle_t *handle,
                               uint8_t phy_addr,
                               uint8_t reg_addr,
                               uint16_t *data_out,
                               uint32_t timeout_ms);

功能:通过 Clause 22 MDIO 读取一个 PHY 寄存器。参数 handle 需提供已填好的 mdc_clock_range;phy_addr、reg_addr 均为 0 ~ 31;data_out 为读回的 16 位值;timeout_ms 为等待 MDIO 完成的超时,0 表示只检查一次。

返回值说明
IM_OK读取成功
IM_ERR_INVALID_PARAMhandle/实例/地址/输出指针非法
IM_ERR_BUSY发起事务前 GMII_AR.GB 已置位(上一次事务未完成)
IM_ERR_TIMEOUT等待 GMII_AR.GB 清零超时;同时置 HAL_MAC_ERROR_MII_TIMEOUT

补充说明:GMII_AR 字段组成为 PA[15:11]、GR[10:6]、CR[5:2](来自 config.mdc_clock_range)、GB[0]=1;等待完成的条件是 GB 清零,完成后读 GMII_DR[15:0]。本接口不检查 HAL 状态机,但 config.mdc_clock_range 需在调用前填好;timeout_ms == 0 时如果第一次检查仍忙,直接返回 IM_ERR_TIMEOUT。HAL 不解析 PHY 寄存器语义,也不做自动协商。

2.3.2 hal_mac_mdio_write

error_code_t hal_mac_mdio_write(hal_mac_handle_t *handle,
                                uint8_t phy_addr,
                                uint8_t reg_addr,
                                uint16_t data,
                                uint32_t timeout_ms);

功能:通过 Clause 22 MDIO 写一个 PHY 寄存器。参数含义同 hal_mac_mdio_read(),data 为待写入的 16 位值。

返回值说明
IM_OK写入成功
IM_ERR_INVALID_PARAMhandle/实例/地址非法
IM_ERR_BUSY发起事务前 GMII_AR.GB 已置位
IM_ERR_TIMEOUT等待 GMII_AR.GB 清零超时;同时置 HAL_MAC_ERROR_MII_TIMEOUT

补充说明:先写 GMII_DR[15:0],再写 GMII_AR = PA | GR | CR | GW | GB(GW[1]=1 表示写事务)。

2.3.3 hal_mac_set_address

error_code_t hal_mac_set_address(hal_mac_handle_t *handle,
                                 uint32_t index,
                                 const uint8_t address[HAL_MAC_ADDRESS_SIZE]);

功能:写 MAC 地址寄存器 0 或 1。参数 handle 为 MAC handle;index 为 0 或 1(< MAC_ADDRESS_REGISTER_COUNT);address 为 6 字节 Ethernet MAC 地址,address[0] 为线上最先发送的字节。

返回:IM_OK;handle/实例/地址指针为空或 index >= 2 时返回 IM_ERR_INVALID_PARAM。

补充说明:

  • 地址高字:ADDRHI = (address[5] << 8) | address[4];低字:ADDRLO = address[3..0] 大端拼接。

2.3.4 hal_mac_set_link_config

error_code_t hal_mac_set_link_config(hal_mac_handle_t *handle,
                                     hal_mac_speed_t speed,
                                     hal_mac_duplex_t duplex);

功能:按请求的速率/双工配置 MAC_CR 的 PS、FES、DM 位,并回写 handle->config。参数 speed 取 HAL_MAC_SPEED_10M 或 HAL_MAC_SPEED_100M;duplex 取 HAL_MAC_DUPLEX_HALF 或 HAL_MAC_DUPLEX_FULL。

返回:IM_OK(同步更新 config.speed/duplex);handle/实例非法或枚举为 UNKNOWN 时返回 IM_ERR_INVALID_PARAM。

位映射:100 Mbps → PS=1、FES=1;10 Mbps → PS=1、FES=0;全双工 → DM=1;半双工 → DM=0。写入前先清 PS|FES|DM,再按映射置位;不改变 MAC_CR 其它位,也不访问 PHY 或 CPM。

2.3.5 hal_mac_set_flow_control

error_code_t hal_mac_set_flow_control(hal_mac_handle_t *handle,
                                      hal_mac_flow_control_t flow_control,
                                      uint16_t pause_time);

功能:写 MAC_FCR,配置 pause frame 时间值和 RX/TX 流控使能。参数 flow_control 取 NONE、RX、TX、RX_TX 的组合;pause_time 写入 MAC_FCR.PT[31:16]。

返回:IM_OK;handle/实例非法或 flow_control 含 RX_TX 之外的位时返回 IM_ERR_INVALID_PARAM。

补充说明:本接口是整寄存器写,DZPQ、PLT、UP、FCB_BPA 等未涉及字段会被清零;不保存流控配置副本,也不在 hal_mac_init() 中自动恢复。

2.4 查询与调试

2.4.1 hal_mac_get_stats

error_code_t hal_mac_get_stats(const hal_mac_handle_t *handle,
                               hal_mac_stats_t *stats_out);

功能:把 handle 内的统计快照拷贝到调用方缓冲区。参数 handle 为 MAC handle;stats_out 为统计输出。返回 IM_OK;参数为空返回 IM_ERR_INVALID_PARAM。本接口只做结构体赋值,不检查实例、状态或描述符类型,也不清零统计。

2.4.2 hal_mac_get_hw_feature

error_code_t hal_mac_get_hw_feature(const hal_mac_handle_t *handle,
                                    uint32_t *value_out);

功能:读取 HWFR 硬件能力寄存器原始值。参数 value_out 为输出指针。返回 IM_OK;handle/实例/输出指针非法时返回 IM_ERR_INVALID_PARAM。HAL 不对 HWFR 做位域解码,位定义见 6.14。

2.4.3 hal_mac_dump_regs

error_code_t hal_mac_dump_regs(const hal_mac_handle_t *handle);

功能:把 MAC 核与 DMA 关键寄存器输出到日志,用于调试。

返回值说明
IM_OK日志已输出
IM_ERR_INVALID_PARAMhandle 为空或实例非法
IM_ERR_UNSUPPORTED未同时启用 CONFIG_SDK_ENABLE_DEBUG_HELPERS 与 CONFIG_MAC_ENABLE_DEBUG_HELPERS

补充说明:

  • 只有两个 Kconfig 开关同时为真时才编译日志代码,否则直接返回 IM_ERR_UNSUPPORTED。

  • 输出寄存器包括:CR、FFR、HTHR、HTLR、GMII_AR、GMII_DR、FCR、VTR、VR、DR、LPI_CSR、LPI_TCR、ISR、IMR、A0HR/A0LR、A1HR/A1LR、DMA_BMR、DMA_RDLAR、DMA_TDLAR、DMA_SR、DMA_OMR、DMA_IER、DMA_MFOCR、DMA_RIWTR、DMA_AHBSR、DMA_CHTDR/CHRDR/CHTBAR/CHRBAR、HWFR。

  • 本接口会读取 DMA_MFOCR,该寄存器为读清寄存器,因此 dump 会顺带清除 missed frame 计数与 overflow 标志。本接口只读寄存器,不改变 HAL 状态。

2.4.4 hal_mac_dump_desc

error_code_t hal_mac_dump_desc(const hal_mac_handle_t *handle);

功能:把 TX/RX 描述符环的 DES0~`DES3` 输出到日志,用于调试。

返回值说明
IM_OK日志已输出
IM_ERR_INVALID_PARAMhandle 为空、tx_desc/rx_desc 为空或指针非法
IM_ERR_NOT_READYtx_desc_count 或 rx_desc_count 为 0
IM_ERR_UNSUPPORTED未同时启用两个调试 Kconfig 开关

补充说明:输出内容是采样快照;DMA 正在运行时描述符会被硬件并发更新,多字输出之间可能不一致。描述符地址按 32 位十六进制打印。

2.5 超时语义与公共行为约定

场景timeout_ms == 0timeout_ms > 0
条件已满足立即成功立即成功
条件未满足检查一次后失败轮询直到超时,每轮之间 msleep(1)
systick 未初始化不依赖 systick,仍可单次检查该次调用失败

各接口在 systick 未初始化且 timeout_ms > 0 时的具体表现:hal_mac_transmit() 返回 IM_ERR_NOT_READY 并置 HAL_MAC_ERROR_TX_TIMEOUT;hal_mac_receive() 返回 IM_ERR_NOT_READY 且不置位;hal_mac_mdio_read()/hal_mac_mdio_write() 返回 IM_ERR_TIMEOUT 并置 HAL_MAC_ERROR_MII_TIMEOUT。

其它公共约定:

  • HAL 内部只在 TX 环相关路径(hal_mac_transmit()、hal_mac_tx_reclaim())使用短临界区,不提供全局锁。

  • HAL 负责描述符与缓冲区的 cache 维护:初始化时对 RX 缓冲区做 clean + invalidate 后交给 DMA;发送前 clean TX 缓冲区;读取 RX 缓冲区前 invalidate;描述符更新后 clean、读取前 invalidate;接收完成释放 RX 描述符时只写回 OWN 并 clean 描述符(不再次刷缓冲区)。

  • HAL 不做动态内存分配;不检查链路状态;不访问 PHY 寄存器语义;不注册 IRQ。

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

3.1 DMA 使用 32 位地址、MTU 与缓冲区上限

DMA_RDLAR、DMA_TDLAR、描述符 DES2/DES3 都只有 32 位。HAL 在 hal_mac_init() 和 hal_mac_transmit() 中把指针转换为 uint32_t,因此描述符与缓冲区必须位于 32 位可寻址空间;超出 32 位的高地址会被截断,属于调用方配置错误。

mtu 最大 2000,大于 1500 时 HAL 置 MAC_CR.TWOKPE;单描述符缓冲区最大 2047 字节,受 TX/RX 描述符 DES1[10:0] 位宽限制;tx_buffer_size/rx_buffer_size 必须 >= mtu 且 <= 2047。一帧必须放进一个缓冲区;HAL 不支持跨描述符 TX 分段,也不接受跨描述符 RX 帧。

3.2 RX FCS 处理

hal_mac_receive() 根据帧的 type/length 字段与 MAC_CR.ACS/CST 判断硬件是否已剥离 FCS:长度字段 < 0x0600 且 ACS=1,或 EtherType >= 0x0600 且 CST=1 时认为已剥离;否则认为 FCS 仍在帧尾,HAL 减去 4 字节。该判断依赖 MAC_CR 当前值,而不是每个描述符都带“FCS 已剥离”标志;若调用方在运行中改变 ACS/CST,需要自行保证判断与硬件行为一致。

3.3 无内部锁

HAL 不提供互斥锁。hal_mac_transmit() 与 hal_mac_tx_reclaim() 用 local_irq_save()/local_irq_restore() 保护 TX 环索引与描述符状态,但多个任务同时调用 hal_mac_transmit() 仍可能因拷贝/描述符更新顺序产生竞争;hal_mac_receive() 没有临界区保护;config、stats、error_code 的读写没有保护。调用方必须自行串行化同一个 handle 的所有访问。

3.4 HAL 不提供 link 自动协商

HAL 只提供 MDIO 读写通道(hal_mac_mdio_read()/hal_mac_mdio_write())、按上层决策写 MAC_CR.PS/FES/DM(hal_mac_set_link_config())和写 MAC_FCR(hal_mac_set_flow_control())。自动协商、PHY 复位、链路状态解码由 PHY 驱动与 Ethernet adapter 完成,见 docs/api/g32s10/middleware/mac_mid_api.md。