我們對g_ethercat_ssc_port0_ext_cfg這個全局變量深入追蹤,其成員變量 g_ether_PHY0,正好是一個PHY實例的詳細描述體。
/* Instance structure to use this module. */
const ether_PHY_instance_t g_ether_PHY0 =
{
.p_ctrl = &g_ether_PHY0_ctrl,
.p_cfg = &g_ether_PHY0_cfg,
.p_api = &g_ether_PHY_on_ether_PHY
};
其中g_ether_PHY0_cfg是pyh實例的配置結構體:
const ether_PHY_cfg_t g_ether_PHY0_cfg =
{
.channel = 0,
.PHY_lsi_address = 0,
.PHY_reset_wait_time = 0x00020000,
.mii_bit_access_wait_time = 0, // Unused
.flow_control = ETHER_PHY_FLOW_CONTROL_DISABLE,
.mii_type = (ether_PHY_mii_type_t) 0, // Unused
.p_context = NULL,
.p_extend = &g_ether_PHY0_extend
};
這里又通過p_extend 做了擴展配置(其實可以合并在一起)如下所示:
const ether_PHY_extend_cfg_t g_ether_PHY0_extend =
{
.port_type = ETHER_PHY_PORT_TYPE_ETHER_CAT,
.PHY_chip = (ether_PHY_chip_t) ETHER_PHY_CHIP_VSC8541,
.mdio_type = ETHER_PHY_MDIO_GMAC,
.bps = ETHER_PHY_SPEED_100,
.duplex = ETHER_PHY_DUPLEX_FULL,
.auto_negotiation = ETHER_PHY_AUTO_NEGOTIATION_ON,
.PHY_reset_pin = BSP_IO_PORT_20_PIN_7,
.PHY_reset_time = 15000,
.p_selector_instance = (ether_selector_instance_t *)&g_ether_selector0,
};
可以看到上面的擴展配置當中,PHY的具體硬件型號都已經列出,如PHY_chip = (ether_PHY_chip_t) ETHER_PHY_CHIP_;
可以看到在示例代碼當中已經支持的PHY如下所示:
/** Identify PHY-LSI */
typedef enum e_ether_PHY_chip
{
ETHER_PHY_CHIP_VSC8541 = (1 << 0), ///< VSC8541
? ?ETHER_PHY_CHIP_KSZ9131 = (1 << 1), ///< KSZ9131
? ?ETHER_PHY_CHIP_KSZ9031 = (1 << 2), ///< KSZ9031
? ?ETHER_PHY_CHIP_KSZ8081 = (1 << 3), ///< KSZ8081
? ?ETHER_PHY_CHIP_KSZ8041 = (1 << 4) ?///< KSZ8041
} ether_PHY_chip_t;
這里具體看一下 g_ether_selector0 這個 ether_selector_instance_t 類型的全局指針,指向 selector driver實例的成員變量:
typedef struct st_ether_selector_instance
{
ether_selector_ctrl_t * p_ctrl; ///< Pointer to the control structure for this instance
? ?ether_selector_cfg_t const * p_cfg; ?///< Pointer to the configuration structure for this instance
? ?ether_selector_api_t const * p_api; ?///< Pointer to the API structure for this instance
} ether_selector_instance_t;
這又是一個類似的結構體,通過三個指針來分別指向結構本身,selector的具體配置,和配置selector過程中所需要用的的成員方法api.
看一下selector的具體配置信息:
typedef struct st_ether_selector_cfg
{
uint8_t port; ///< Port number
? ?ether_selector_PHYlink_polarity_t PHYlink; ///< PHY link signal polarity
? ?ether_selector_interface_t interface; ? ? ?///< Converter mode
? ?ether_selector_speed_t ? ? speed; ? ? ? ? ?///< Converter Speed
? ?ether_selector_duplex_t ? ?duplex; ? ? ? ? ///< Converter Duplex
? ?ether_selector_ref_clock_t ref_clock; ? ? ?///< Converter REF_CLK
? ?void const ? ? ? ? ? ? ? * p_extend; ? ? ? ///< Placeholder for user extension.
} ether_selector_cfg_t;
可以看到selector 對應的端口號,PHY連接信號對應的極性,接口模式,速率,全雙工,以及外部時鐘輸入。再看一下配置selector的過程中所需要用到的API函數:
const ether_selector_api_t g_ether_selector_on_ether_selector =
{
.open = R_ETHER_SELECTOR_Open,
.converterSet = R_ETHER_SELECTOR_ConverterSet,
.close = R_ETHER_SELECTOR_Close,
.versionGet = R_ETHER_SELECTOR_VersionGet
};
其最主要的成員方法就是R_ETHER_SELECTOR_Open做了些什么:
先初始化ETHER_SELECTOR
/* One time initialization for all ETHER_SELECTOR instances. */ r_ether_selector_state_initialize(); /* Unlock write access protection for Ethernet subsystem registers */ r_ether_selector_reg_protection_disable(p_reg_ethss); /* Set the function of Ethernet ports. */ sw_mode = ETHER_SELECTOR_CFG_MODE; p_reg_ethss->MODCTRL_b.SW_MODE = sw_mode & ETHER_SELECTOR_MODCTRL_BIT_SWMODE_MASK; /* Set the MAC of all port for half-duplex. */ p_reg_ethss->SWDUPC_b.PHY_DUPLEX = 0; /* Set all Ethernet switch port to select not use 10Mbps. */ p_reg_ethss->SWCTRL_b.SET10 = 0;
根據端口號來選擇對應控制寄存器
/* Set RGMII/RMII Converter configuration */
switch (port)
{
case 0:
{
p_reg_convctrl = (uint32_t *) &p_reg_ethss->CONVCTRL[0];
break;
}
case 1:
{
p_reg_convctrl = (uint32_t *) &p_reg_ethss->CONVCTRL[1];
break;
}
case 2:
default:
{
p_reg_convctrl = (uint32_t *) &p_reg_ethss->CONVCTRL[2];
break;
}
}
根據指向selector的配置信息:
const ether_selector_cfg_t g_ether_selector0_cfg =
{
.port = 0,
.PHYlink = ETHER_SELECTOR_PHYLINK_POLARITY_LOW,
.interface = ETHER_SELECTOR_INTERFACE_RGMII,
.speed = ETHER_SELECTOR_SPEED_100MBPS,
.duplex = ETHER_SELECTOR_DUPLEX_FULL,
.ref_clock = ETHER_SELECTOR_REF_CLOCK_INPUT,
.p_extend = NULL,
};
來對CONVCTRL[port_number]寄存器做相應的配置

這里結合RZ/T2M的用戶手冊,很容易理解其中的意思:

結合代碼來看,總體ETHER_SELECTOR 的驅動的配置流程圖臺下所示:

在對ETHER_SELECTOR驅動做完配置后,下面具體看一下對ETHER_PHY_CHIP這個PHY,代碼具體做了哪些操作:
首先是做初始化:

oid ether_PHY_targets_initialize_vsc8541 (ether_PHY_instance_ctrl_t * p_instance_ctrl)
{
/* Vendor Specific PHY Registers */
#define ETHER_PHY_REG_LED_MODE_SELECT (0x1D)
#define ETHER_PHY_REG_LED_BEHAVIOR (0x1E)
#define ETHER_PHY_REG_EXTEND_GPIO_PAGE (0x1F)
...
這個初始化函數,并沒有對IEEE 標準規定的16個寄存器做讀寫操作,只對廠商自定義的寄存器做了配置。初始化完成之后,對是否打開自動協商的功能對PHY進行了讀寫:


這里可以看到對PHY芯生來說,需要配置的寄存器并不是很多,大多數情況下,把自動協商寄存器配置好,就可以了。除此之后就是廠商自定義的寄存器的一些自定義的功能。這部分功能需要結合用戶手冊來理解和使用,大部分也是用來調試和指示的作用以及一些IEEE基本標準之外的特色功能,比如節能標準之類的。
對于用戶說來,搞清楚數據結構之間的關聯,剩下的就是驅動代碼的執行邏輯,考慮到執行邏輯并不復雜,這里不展開來說。用戶可以參考錄屏材料進一步深入了解。
其它
經過驗證的PHY芯片列表:

審核編輯:劉清
-
以太網
+關注
關注
41文章
5936瀏覽量
179761 -
寄存器
+關注
關注
31文章
5590瀏覽量
129248 -
PHY
+關注
關注
2文章
331瀏覽量
53836
發布評論請先 登錄
車載以太網PHY標準分布
還在為以太網PHY缺芯改版煩惱嗎?

以太網PHY寄存器分析 以太網PHY驅動軟件配置
評論