【STM32F429】第6章 RL-TCPnet V7.X底层驱动说明
最新教程下載:http://www.armbbs.cn/forum.php?mod=viewthread&tid=95243
第6章?? RL-TCPnet底層驅(qū)動說明
本章節(jié)為大家講解RL-TCPnet的底層驅(qū)動,主要是STM32自帶MAC的驅(qū)動實現(xiàn)和PHY的驅(qū)動實現(xiàn)。
目錄
第6章?? RL-TCPnet底層驅(qū)動說明
6.1?? 初學(xué)者重要提示
6.2?? MAC+PHY驅(qū)動實現(xiàn)方案
6.3?? CMSIS-Driver簡介和驅(qū)動工作流程
6.4?? CMSIS-Driver的PHY底層驅(qū)動實現(xiàn)
6.4.1????? DM9161和DM9162的區(qū)別
6.4.2????? 函數(shù)GetVersion
6.4.3????? 函數(shù)Initialize
6.4.4????? 函數(shù)Uninitialize
6.4.5????? 函數(shù)PowerControl
6.4.6????? 函數(shù)SetInterface
6.4.7????? 函數(shù)SetMode
6.4.8????? 函數(shù)GetLinkState
6.4.9????? 函數(shù)GetLinkInfo
6.5?? CMSIS-Driver的MAC底層驅(qū)動實現(xiàn)
6.5.1????? 函數(shù)GetVersion
6.5.2????? 函數(shù)GetCapabilities
6.5.3????? 函數(shù)Initialize
6.5.4????? 函數(shù)Uninitialize
6.5.5????? 函數(shù)PowerControl
6.5.6????? 函數(shù)GetMacAddress
6.5.7????? 函數(shù)SetMacAddress
6.5.8????? 函數(shù)SetAddressFilter
6.5.9????? 函數(shù)SendFrame
6.5.10 函數(shù)ReadFrame
6.5.11 函數(shù)GetRxFrameSize
6.5.12 函數(shù)GetRxFrameTime
6.5.13 函數(shù)GetTxFrameSize
6.5.14 函數(shù)ControlTimer
6.5.15 函數(shù)Control
6.5.16 函數(shù)PHY_Read
6.5.17 函數(shù)PHY_Write
6.6?? 總結(jié)
6.1?? 初學(xué)者重要提示
6.2?? MAC+PHY驅(qū)動實現(xiàn)方案
STM32F4自帶MAC,所以只需外置PHY芯片即可使用以太網(wǎng),示意圖如下:
當(dāng)前V5開發(fā)板使用的PHY芯片是DM9162。反映到硬件設(shè)計上,原圖如下:
?
通過這個原理圖,我們要注意以下兩點(diǎn):
- ? 1.8V的電壓是PHY芯片DM916x自己產(chǎn)生的。
- ? PHY芯片的地址由PHYAD[0:3]引腳決定,當(dāng)前是將PHYAD[0]引腳接了一個上拉電阻,也就是說DM916x的地址是0x01。
?
教程配套的開發(fā)板采用的RMII接口,即下面這種硬件接口方式:
RMII接口降低了 10/100Mbps下微控制器以太網(wǎng)外設(shè)與外部PHY間的引腳數(shù)。根據(jù)IEEE 802.3u標(biāo)準(zhǔn), MII包括16個數(shù)據(jù)和控制信號的引腳。RMII規(guī)范將引腳數(shù)減少為7個(引腳數(shù)減少62.5%)。RMII具有以下特性:
- ? 支持10Mbps和100Mbps的運(yùn)行速率。
- ? 參考時鐘必須是 50 MHz。
- ? 相同的參考時鐘必須從外部提供給 MAC 和外部以太網(wǎng) PHY。
- ? 它提供了獨(dú)立的2位寬(雙位)的發(fā)送和接收數(shù)據(jù)路徑,即發(fā)生和接收都是占用了兩個引腳。
6.3?? CMSIS-Driver簡介和驅(qū)動工作流程
這個是ARM做好的驅(qū)動框架,支持的外設(shè)如下:
針對不同廠商,ARM會出一個完整的驅(qū)動包,比如STM32F4系列,在MDK安裝目錄的此路徑下(前提是大家安裝了STM32H7軟件包):ARM\PACK\Keil\STM32F4xx_DFP\2.14.0\CMSIS\Driver。
ARM做的這個驅(qū)動跟HAL庫有什么區(qū)別呢?ARM做的這個庫要調(diào)用到HAL的一些API(H7版的有調(diào)用到,F4版的很少調(diào)用到,基本是獨(dú)立的),然后封裝了一些比較好用的API,方便用戶調(diào)用。
關(guān)于這些不同外設(shè)的驅(qū)動文件,它們都有統(tǒng)一的API函數(shù),調(diào)用流程如下:
關(guān)于這個驅(qū)動的流程,大家有個認(rèn)識即可,網(wǎng)絡(luò)協(xié)議棧會直接調(diào)用這些API進(jìn)行操作,無需用戶去調(diào)用。
6.4?? CMSIS-Driver的PHY底層驅(qū)動實現(xiàn)
PHY驅(qū)動由CMSIS-Driver軟件包提供,當(dāng)前支持的PHY如下(位于MDK安裝路徑ARM\CMSIS-Driver\2.4.0\ETH,數(shù)字2.4.0表示當(dāng)前的CMSIS-Driver版本):
這些驅(qū)動文件主要分為兩類:
- ? 以ETH開頭的,這些芯片是MAC+PHY二合一。
- ? 以PHY開頭的,這些芯片僅是個PHY。
?
CMSIS-Driver現(xiàn)有的驅(qū)動里面是沒有DM9162,所以需要用戶自己實現(xiàn),這里將DM9162的實現(xiàn)函數(shù)逐一為大家做個說明。CMSIS-Driver已經(jīng)定義好了API,用戶實現(xiàn)每個API的具體功能即可。
6.4.1????? DM9161和DM9162的區(qū)別
早期我們發(fā)布的STM32F407開發(fā)板的PHY芯片使用的是DM9161,現(xiàn)在這個芯片基本已經(jīng)停產(chǎn),所以已經(jīng)統(tǒng)一改成使用DM9162,這兩個型號主要在以下兩個地方有區(qū)別,其它基本都一樣。
- ? 兩個PHY芯片的的ID不一樣,DM9161的ID是0x0181B8B1,DM9162的ID是0x0181B8A0。
- ? 系統(tǒng)剛上電時,DM9161的ID寄存器支持立即讀取,但是DM9162不支持,這一點(diǎn)用戶在使用的時候要特別注意。但是DM9161和DM9162都支持立即寫寄存器BMCR,所以當(dāng)前的操作就是直接對寄存器BMCR發(fā)復(fù)位命令,然后再進(jìn)行相關(guān)設(shè)置。
?
對于這兩個芯片,了解這兩點(diǎn)區(qū)別就可以了。另外,這兩個芯片的手冊和其它的相關(guān)知識在這個帖子里面進(jìn)行了簡單的匯總:http://www.armbbs.cn/forum.php?mod=viewthread&tid=19577
6.4.2????? 函數(shù)GetVersion
函數(shù)原型:
static ARM_DRIVER_VERSION GetVersion (void) {return DriverVersion; }函數(shù)描述:
用于獲取當(dāng)前的PHY驅(qū)動版本。
6.4.3????? 函數(shù)Initialize
函數(shù)原型:
static int32_t Initialize (ARM_ETH_PHY_Read_t fn_read, ARM_ETH_PHY_Write_t fn_write) {if ((fn_read == NULL) || (fn_write == NULL)) { return ARM_DRIVER_ERROR_PARAMETER; }if ((PHY.flags & PHY_INIT) == 0U) {/* Register PHY read/write functions. */PHY.reg_rd = fn_read;PHY.reg_wr = fn_write;PHY.bmcr = 0U;PHY.flags = PHY_INIT;}return ARM_DRIVER_OK; }函數(shù)描述:
初始化讀寫PHY芯片所需要的API
函數(shù)參數(shù):
- ? 第1個參數(shù)是讀PHY芯片API地址。
- ? 第2個參數(shù)是寫PHY芯片API地址。
- ? 返回值,無參數(shù)錯誤返回ARM_DRIVER_OK。有參數(shù)錯誤返回ARM_DRIVER_ERROR_PARAMETER。
6.4.4????? 函數(shù)Uninitialize
函數(shù)原型:
static int32_t Uninitialize (void) {PHY.reg_rd = NULL;PHY.reg_wr = NULL;PHY.bmcr = 0U;PHY.flags = 0U;return ARM_DRIVER_OK; }函數(shù)描述:
復(fù)位讀寫PHY芯片所需要的API。
函數(shù)參數(shù):
- ? 返回值,返回ARM_DRIVER_OK
6.4.5????? 函數(shù)PowerControl
函數(shù)原型:
static int32_t PowerControl (ARM_POWER_STATE state) {uint16_t val;switch ((int32_t)state) {/* 將PHY斷電 */case ARM_POWER_OFF:/* 初始化狀態(tài)才可以配置POWER OFF */if ((PHY.flags & PHY_INIT) == 0U) {return ARM_DRIVER_ERROR;}PHY.flags &= ~PHY_POWER;PHY.bmcr = BMCR_POWER_DOWN;/* 設(shè)置BMCR寄存器,斷電 */return (PHY.reg_wr(ETH_PHY_ADDR, REG_BMCR, PHY.bmcr));/* PHY上電,并清除BMCR寄存器 */case ARM_POWER_FULL:/* 初始化狀態(tài)才可以配置POWER FULL */ if ((PHY.flags & PHY_INIT) == 0U) {return ARM_DRIVER_ERROR;}/* 已經(jīng)處于POWER ON狀態(tài),直接返回OK */if (PHY.flags & PHY_POWER) {return ARM_DRIVER_OK;}/* 讀取設(shè)備 */PHY.reg_rd(ETH_PHY_ADDR, REG_PHYIDR1, &val);/* 讀取ID1 */if (val != PHY_ID1) {return ARM_DRIVER_ERROR_UNSUPPORTED;}PHY.reg_rd(ETH_PHY_ADDR, REG_PHYIDR2, &val);/* 讀取ID2, 此處做了一個特別處理,屏蔽后面8個bit,方便DM9162和DM9161都可以識別,因為這兩個PHY后面的ID不同。*/if ((val & 0xFF00) != PHY_ID2) {return ARM_DRIVER_ERROR_UNSUPPORTED;}/* DM916X用不到這個 */#if (ETH_PHY_REF_CLK_50M != 0)PHY.reg_rd(ETH_PHY_ADDR, REG_PHYCR2, &val);val |= PHYCR2_REF_CLK_SELECT;PHY.reg_wr(ETH_PHY_ADDR, REG_PHYCR2, val);#endifPHY.bmcr = 0U;/* BMCR寄存器清零 */if (PHY.reg_wr(ETH_PHY_ADDR, REG_BMCR, PHY.bmcr) != ARM_DRIVER_OK) {return ARM_DRIVER_ERROR;}PHY.flags |= PHY_POWER;return ARM_DRIVER_OK;/* 不支持低功耗操作 */case ARM_POWER_LOW:default:return ARM_DRIVER_ERROR_UNSUPPORTED;} }函數(shù)描述:
用于控制PHY的上電和斷電。
函數(shù)參數(shù):
- ? 第1個參數(shù)是PHY配置
- ? ARM_POWER_OFF 表示斷電,程序此處做了BMCR寄存器斷電操作。
- ? ARM_POWER_FULL 表示上電,程序此處讀取PHY的ID,并清除BMCR寄存器。
- ? ARM_POWER_LOW 表示低功耗,程序此處不支持。
- ? 第2個參數(shù)是寫PHY芯片API地址。
- ? 返回值,設(shè)置正確返回ARM_DRIVER_OK,設(shè)置錯誤返回ARM_DRIVER_ERROR,而ARM_DRIVER_ERROR_UNSUPPORTED表示不支持。
6.4.6????? 函數(shù)SetInterface
函數(shù)原型:
static int32_t SetInterface (uint32_t interface) {int32_t status;if ((PHY.flags & PHY_POWER) == 0U) { return ARM_DRIVER_ERROR; }/* 僅作了RMII接口支持 */switch (interface) {case ARM_ETH_INTERFACE_RMII: status = ARM_DRIVER_OK; break;default:status = ARM_DRIVER_ERROR_UNSUPPORTED; break;}return (status); }函數(shù)描述:
用于配置使用SMII,RMII還是MII接口外接的PHY芯片。
函數(shù)參數(shù):
- ? 第1個參數(shù)設(shè)置使用的PHY接口類型。
- ? ARM_ETH_INTERFACE_MII,Media Independent Interface (MII)
- ? ARM_ETH_INTERFACE_RMII,Reduced Media Independent Interface (RMII)
- ? ARM_ETH_INTERFACE_SMII,Serial Media Independent Interface (SMII)
- ? 返回值,設(shè)置正確返回ARM_DRIVER_OK,設(shè)置錯誤返回ARM_DRIVER_ERROR,而ARM_DRIVER_ERROR_UNSUPPORTED表示不支持。
6.4.7????? 函數(shù)SetMode
函數(shù)原型:
static int32_t SetMode (uint32_t mode) {uint16_t val;/* 上電狀態(tài)才可以配置 */if ((PHY.flags & PHY_POWER) == 0U) { return ARM_DRIVER_ERROR; }val = PHY.bmcr & BMCR_POWER_DOWN;/* 速度配置10M或者100M */switch (mode & ARM_ETH_PHY_SPEED_Msk) {case ARM_ETH_PHY_SPEED_10M:break;case ARM_ETH_PHY_SPEED_100M:val |= BMCR_SPEED_SELECT;break;default:return ARM_DRIVER_ERROR_UNSUPPORTED;}/* 全雙工或者半雙工配置 */switch (mode & ARM_ETH_PHY_DUPLEX_Msk) {case ARM_ETH_PHY_DUPLEX_HALF:break;case ARM_ETH_PHY_DUPLEX_FULL:val |= BMCR_DUPLEX_MODE;break;default:return ARM_DRIVER_ERROR_UNSUPPORTED;}/* 自動協(xié)商配置使能 */if (mode & ARM_ETH_PHY_AUTO_NEGOTIATE) {val |= BMCR_ANEG_EN;}/* 回環(huán)配置使能,方便回環(huán)測試 */if (mode & ARM_ETH_PHY_LOOPBACK) {val |= BMCR_LOOPBACK;} /* 設(shè)置隔離,電氣隔離RMII/MII/SMII接口 */if (mode & ARM_ETH_PHY_ISOLATE) {val |= BMCR_ISOLATE;}PHY.bmcr = val;return (PHY.reg_wr(ETH_PHY_ADDR, REG_BMCR, PHY.bmcr)); }函數(shù)描述:
用于設(shè)置PHY芯片的工作模式。
函數(shù)參數(shù):
- ? 第1個參數(shù)設(shè)置工作模式,這幾項支持或操作。
- ? 返回值,設(shè)置正確返回ARM_DRIVER_OK,設(shè)置錯誤返回ARM_DRIVER_ERROR,而ARM_DRIVER_ERROR_UNSUPPORTED表示不支持。
6.4.8????? 函數(shù)GetLinkState
函數(shù)原型:
static ARM_ETH_LINK_STATE GetLinkState (void) {ARM_ETH_LINK_STATE state;uint16_t val = 0U;if (PHY.flags & PHY_POWER) {PHY.reg_rd(ETH_PHY_ADDR, REG_BMSR, &val);}state = (val & BMSR_LINK_STAT) ? ARM_ETH_LINK_UP : ARM_ETH_LINK_DOWN;return (state); }函數(shù)描述:
用于獲取網(wǎng)線插拔狀態(tài)。
函數(shù)參數(shù):
- ? 返回值,返回ARM_ETH_LINK_UP表示網(wǎng)線在連接狀態(tài),返回ARM_ETH_LINK_DOWN表示網(wǎng)線處于斷開狀態(tài)。
6.4.9????? 函數(shù)GetLinkInfo
函數(shù)原型:
static ARM_ETH_LINK_INFO GetLinkInfo (void) {ARM_ETH_LINK_INFO info;uint16_t val = 0U;if (PHY.flags & PHY_POWER) {/* 讀取PHY DSCSR 寄存器 */PHY.reg_rd(ETH_PHY_ADDR, REG_DSCSR, &val);}/* 獲取速度和雙工模式 */info.speed = ((val & DSCSR_100M_FD)|(val & DSCSR_100M_HD)) ? ARM_ETH_SPEED_100M : ARM_ETH_SPEED_10M;info.duplex = ((val & DSCSR_100M_FD)|(val & DSCSR_10M_FD)) ? ARM_ETH_DUPLEX_FULL : ARM_ETH_DUPLEX_HALF;return (info); }函數(shù)描述:
用于獲取速度和雙工模式。
函數(shù)參數(shù):
- ?返回值記錄速度(10Mbps或者100Mbps)和雙工模式(半雙工或者全雙工)。
6.5?? CMSIS-Driver的MAC底層驅(qū)動實現(xiàn)
KEIL已經(jīng)為STM32F4制作好MAC驅(qū)動文件EMAC_STM32F4xx.c。我們這里將相關(guān)實現(xiàn)函數(shù)為大家做個說明。
6.5.1????? 函數(shù)GetVersion
函數(shù)原型:
static ARM_DRIVER_VERSION GetVersion (void) {return DriverVersion; }函數(shù)描述:
用于獲取當(dāng)前的MAC驅(qū)動版本。
6.5.2????? 函數(shù)GetCapabilities
函數(shù)原型:
#ifndef EMAC_CHECKSUM_OFFLOAD #define EMAC_CHECKSUM_OFFLOAD 1 #endifstatic const ARM_ETH_MAC_CAPABILITIES DriverCapabilities = {(EMAC_CHECKSUM_OFFLOAD != 0) ? 1U : 0U, /* checksum_offload_rx_ip4 */(EMAC_CHECKSUM_OFFLOAD != 0) ? 1U : 0U, /* checksum_offload_rx_ip6 */(EMAC_CHECKSUM_OFFLOAD != 0) ? 1U : 0U, /* checksum_offload_rx_udp */(EMAC_CHECKSUM_OFFLOAD != 0) ? 1U : 0U, /* checksum_offload_rx_tcp */(EMAC_CHECKSUM_OFFLOAD != 0) ? 1U : 0U, /* checksum_offload_rx_icmp */(EMAC_CHECKSUM_OFFLOAD != 0) ? 1U : 0U, /* checksum_offload_tx_ip4 */(EMAC_CHECKSUM_OFFLOAD != 0) ? 1U : 0U, /* checksum_offload_tx_ip6 */(EMAC_CHECKSUM_OFFLOAD != 0) ? 1U : 0U, /* checksum_offload_tx_udp */(EMAC_CHECKSUM_OFFLOAD != 0) ? 1U : 0U, /* checksum_offload_tx_tcp */(EMAC_CHECKSUM_OFFLOAD != 0) ? 1U : 0U, /* checksum_offload_tx_icmp */(ETH_MII != 0) ?ARM_ETH_INTERFACE_MII :ARM_ETH_INTERFACE_RMII, /* media_interface */0U, /* mac_address */1U, /* event_rx_frame */1U, /* event_tx_frame */1U, /* event_wakeup */(EMAC_TIME_STAMP != 0) ? 1U : 0U /* precision_timer */ #if (defined(ARM_ETH_MAC_API_VERSION) && (ARM_ETH_MAC_API_VERSION >= 0x201U)) , 0U /* reserved bits */ #endif };static ARM_ETH_MAC_CAPABILITIES GetCapabilities (void) {return DriverCapabilities; }函數(shù)描述:
用于獲取MAC的硬件功能。
從當(dāng)前的宏定義來看,支持發(fā)送和接收的IP4,IP6,UDP,TCP和ICMP的硬件校驗和計算。
6.5.3????? 函數(shù)Initialize
函數(shù)原型:
static int32_t Initialize (ARM_ETH_MAC_SignalEvent_t cb_event) { #if defined(RTE_DEVICE_FRAMEWORK_CLASSIC)GPIO_InitTypeDef GPIO_InitStruct;const ETH_PIN *io; #endif/* 使能SYSCFG時鐘 */RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN;#if (ETH_MII == 0)SYSCFG->PMC |= SYSCFG_PMC_MII_RMII_SEL;#elseSYSCFG->PMC &= ~SYSCFG_PMC_MII_RMII_SEL;#endif#if defined(RTE_DEVICE_FRAMEWORK_CLASSIC)/* 配置以太網(wǎng)引腳 */GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;GPIO_InitStruct.Alternate = GPIO_AF11_ETH;for (io = eth_pins; io != ð_pins[sizeof(eth_pins)/sizeof(ETH_PIN)]; io++) {Enable_GPIO_Clock (io->port);GPIO_InitStruct.Pin = io->pin;HAL_GPIO_Init (io->port, &GPIO_InitStruct);}#elseheth.Instance = ETH;#endif/* 清空控制結(jié)構(gòu)體 */memset ((void *)&Emac, 0, sizeof (EMAC_CTRL));Emac.cb_event = cb_event;Emac.flags = EMAC_FLAG_INIT;return ARM_DRIVER_OK; }函數(shù)描述:
用于初始化MAC,配置以太網(wǎng)引腳,注冊回調(diào)函數(shù)。
函數(shù)參數(shù):
- ? 第1個參數(shù)用于注冊回調(diào)函數(shù)。
- ? 返回值,固定返回ARM_DRIVER_OK。
6.5.4????? 函數(shù)Uninitialize
函數(shù)原型:
static int32_t Uninitialize (void) { #if defined(RTE_DEVICE_FRAMEWORK_CLASSIC)const ETH_PIN *io;/* 復(fù)位以太網(wǎng)引腳配置 */for (io = eth_pins; io != ð_pins[sizeof(eth_pins)/sizeof(ETH_PIN)]; io++) {HAL_GPIO_DeInit(io->port, io->pin);} #elseheth.Instance = NULL; #endifEmac.flags &= ~EMAC_FLAG_INIT;return ARM_DRIVER_OK; }函數(shù)描述:
復(fù)位初始化。
函數(shù)參數(shù):
- ? 返回值,固定返回ARM_DRIVER_OK。
6.5.5????? 函數(shù)PowerControl
函數(shù)原型:
static int32_t PowerControl (ARM_POWER_STATE state) {uint32_t hclk, clkdiv;if ((state != ARM_POWER_OFF) && (state != ARM_POWER_FULL) && (state != ARM_POWER_LOW)) {return ARM_DRIVER_ERROR_UNSUPPORTED;}switch (state) {/* 關(guān)閉電源 */case ARM_POWER_OFF:內(nèi)容較多,省略未寫break;/* 低功耗 */case ARM_POWER_LOW:return ARM_DRIVER_ERROR_UNSUPPORTED;/* 上電 */case ARM_POWER_FULL:內(nèi)容較多,省略未寫break;}return ARM_DRIVER_OK; }函數(shù)描述:
用于控制MAC的上電和斷電。
函數(shù)參數(shù):
- ? 第1個參數(shù)是MAC配置
- ? ARM_POWER_OFF 表示斷電,程序此處做了MAC復(fù)位。
- ? ARM_POWER_FULL 表示上電,程序此處初始化MAC。
- ? ARM_POWER_LOW 表示低功耗,程序此處不支持。
- ? 返回值,設(shè)置正確返回ARM_DRIVER_OK,設(shè)置錯誤返回ARM_DRIVER_ERROR,而ARM_DRIVER_ERROR_UNSUPPORTED表示不支持。
6.5.6????? 函數(shù)GetMacAddress
函數(shù)原型:
static int32_t GetMacAddress (ARM_ETH_MAC_ADDR *ptr_addr) {uint32_t val;if (ptr_addr == NULL) {return ARM_DRIVER_ERROR_PARAMETER;}if ((Emac.flags & EMAC_FLAG_POWER) == 0U) {return ARM_DRIVER_ERROR;}val = ETH->MACA0HR;ptr_addr->b[5] = (uint8_t)(val >> 8);ptr_addr->b[4] = (uint8_t)(val);val = ETH->MACA0LR;ptr_addr->b[3] = (uint8_t)(val >> 24);ptr_addr->b[2] = (uint8_t)(val >> 16);ptr_addr->b[1] = (uint8_t)(val >> 8);ptr_addr->b[0] = (uint8_t)(val);return ARM_DRIVER_OK; }函數(shù)描述:
用于獲取MAC地址。
函數(shù)參數(shù):
- ? 第1個參數(shù)用于存儲獲取的MAC地址。
- ? 返回值,設(shè)置正確返回ARM_DRIVER_OK,設(shè)置錯誤返回ARM_DRIVER_ERROR,而ARM_DRIVER_ERROR_PARAMETER表示參數(shù)錯誤。
6.5.7????? 函數(shù)SetMacAddress
函數(shù)原型:
static int32_t SetMacAddress (const ARM_ETH_MAC_ADDR *ptr_addr) {if (ptr_addr == NULL) {return ARM_DRIVER_ERROR_PARAMETER;}if ((Emac.flags & EMAC_FLAG_POWER) == 0U) {return ARM_DRIVER_ERROR;}/* Set Ethernet MAC Address registers */ETH->MACA0HR = ((uint32_t)ptr_addr->b[5] << 8) | (uint32_t)ptr_addr->b[4];ETH->MACA0LR = ((uint32_t)ptr_addr->b[3] << 24) | ((uint32_t)ptr_addr->b[2] << 16) |((uint32_t)ptr_addr->b[1] << 8) | (uint32_t)ptr_addr->b[0];return ARM_DRIVER_OK; }函數(shù)描述:
用于設(shè)置本身的MAC地址。包含這個MAC地址的以太網(wǎng)幀才會被這個芯片所接受。也可以通過函數(shù)ARM_ETH_MAC_SetAddressFilter設(shè)置接收其它的MAC地址。除此之外,還可以通過函數(shù)ARM_ETH_MAC_Control 的參數(shù)ARM_ETH_MAC_CONFIGURE設(shè)置廣播和組播。
函數(shù)參數(shù):
- ? 第1個參數(shù)是MAC地址。
- ? 返回值,設(shè)置正確返回ARM_DRIVER_OK,設(shè)置錯誤返回ARM_DRIVER_ERROR,而ARM_DRIVER_ERROR_PARAMETER表示參數(shù)錯誤。
6.5.8????? 函數(shù)SetAddressFilter
函數(shù)原型:
static int32_t SetAddressFilter (const ARM_ETH_MAC_ADDR *ptr_addr, uint32_t num_addr) {uint32_t crc;if ((ptr_addr == NULL) && (num_addr != 0)) {return ARM_DRIVER_ERROR_PARAMETER;}if ((Emac.flags & EMAC_FLAG_POWER) == 0U) {return ARM_DRIVER_ERROR;}/* 使用單播過濾前三個MAC */ETH->MACFFR &= ~(ETH_MACFFR_HPF | ETH_MACFFR_HM);ETH->MACHTHR = 0U; ETH->MACHTLR = 0U;if (num_addr == 0U) {ETH->MACA1HR = 0U; ETH->MACA1LR = 0U;ETH->MACA2HR = 0U; ETH->MACA2LR = 0U;ETH->MACA3HR = 0U; ETH->MACA3LR = 0U;return ARM_DRIVER_OK;}ETH->MACA1HR = ((uint32_t)ptr_addr->b[5] << 8) | (uint32_t)ptr_addr->b[4] | ETH_MACA1HR_AE;ETH->MACA1LR = ((uint32_t)ptr_addr->b[3] << 24) | ((uint32_t)ptr_addr->b[2] << 16) |((uint32_t)ptr_addr->b[1] << 8) | (uint32_t)ptr_addr->b[0];num_addr--;if (num_addr == 0U) {ETH->MACA2HR = 0U; ETH->MACA2LR = 0U;ETH->MACA3HR = 0U; ETH->MACA3LR = 0U;return ARM_DRIVER_OK;}ptr_addr++;ETH->MACA2HR = ((uint32_t)ptr_addr->b[5] << 8) | (uint32_t)ptr_addr->b[4] | ETH_MACA2HR_AE;ETH->MACA2LR = ((uint32_t)ptr_addr->b[3] << 24) | ((uint32_t)ptr_addr->b[2] << 16) |((uint32_t)ptr_addr->b[1] << 8) | (uint32_t)ptr_addr->b[0];num_addr--;if (num_addr == 0U) {ETH->MACA3HR = 0U; ETH->MACA3LR = 0U;return ARM_DRIVER_OK;}ptr_addr++;ETH->MACA3HR = ((uint32_t)ptr_addr->b[5] << 8) | (uint32_t)ptr_addr->b[4] | ETH_MACA3HR_AE;ETH->MACA3LR = ((uint32_t)ptr_addr->b[3] << 24) | ((uint32_t)ptr_addr->b[2] << 16) |((uint32_t)ptr_addr->b[1] << 8) | (uint32_t)ptr_addr->b[0];num_addr--;if (num_addr == 0U) {return ARM_DRIVER_OK;}ptr_addr++;/* 計算剩余MAC地址的64bit Hash表 */for ( ; num_addr; ptr_addr++, num_addr--) {crc = crc32_data (&ptr_addr->b[0], 6U) >> 26;if (crc & 0x20U) {ETH->MACHTHR |= (1U << (crc & 0x1FU));}else {ETH->MACHTLR |= (1U << crc);}}/* 使能單播和Hash地址過濾 */ETH->MACFFR |= ETH_MACFFR_HPF | ETH_MACFFR_HM;return ARM_DRIVER_OK; }函數(shù)描述:
用于以太網(wǎng)MAC接收地址過濾,通過這個函數(shù)可以設(shè)置此設(shè)備可以接收到的MAC地址(設(shè)備本身MAC以外的地址)。MAC還可以通過函數(shù)ARM_ETH_MAC_Control 的參數(shù)ARM_ETH_MAC_CONFIGURE設(shè)置廣播和組播。
函數(shù)參數(shù):
- ? 第1個參數(shù)是MAC地址列表。
- ? 第2個參數(shù)是MAC地址個數(shù)。
- ? 返回值,設(shè)置正確返回ARM_DRIVER_OK,設(shè)置錯誤返回ARM_DRIVER_ERROR,而ARM_DRIVER_ERROR_PARAMETER表示參數(shù)錯誤。
6.5.9????? 函數(shù)SendFrame
函數(shù)原型:
static int32_t SendFrame (const uint8_t *frame, uint32_t len, uint32_t flags) {uint8_t *dst = Emac.frame_end;uint32_t ctrl;if ((frame == NULL) || (len == 0U)) {return ARM_DRIVER_ERROR_PARAMETER;}if ((Emac.flags & EMAC_FLAG_POWER) == 0U) {return ARM_DRIVER_ERROR;}if (dst == NULL) {/* 啟動新的傳輸幀 */if (tx_desc[Emac.tx_index].CtrlStat & DMA_TX_OWN) {/* 傳輸忙 */return ARM_DRIVER_ERROR_BUSY;}dst = tx_desc[Emac.tx_index].Addr;tx_desc[Emac.tx_index].Size = len;}else {/* 分步傳輸 */tx_desc[Emac.tx_index].Size += len;}/* 快速復(fù)制數(shù)據(jù)到ETH-DMA */for ( ; len > 7U; dst += 8, frame += 8, len -= 8U) {__UNALIGNED_UINT32_WRITE(&dst[0], __UNALIGNED_UINT32_READ(&frame[0]));__UNALIGNED_UINT32_WRITE(&dst[4], __UNALIGNED_UINT32_READ(&frame[4]));}/* 復(fù)制剩余字節(jié) */for ( ; len > 1U; dst += 2, frame += 2, len -= 2U) {__UNALIGNED_UINT16_WRITE(&dst[0], __UNALIGNED_UINT16_READ(&frame[0]));}if (len > 0U) { dst++[0] = frame++[0]; }if (flags & ARM_ETH_MAC_TX_FRAME_FRAGMENT) {/* 還有數(shù)據(jù),記錄當(dāng)前寫入位置 */Emac.frame_end = dst;return ARM_DRIVER_OK;}/* 幀就緒,發(fā)送給DMA */ctrl = tx_desc[Emac.tx_index].CtrlStat & ~DMA_TX_CIC; #if (EMAC_CHECKSUM_OFFLOAD != 0)if (Emac.tx_cks_offload) {/* The following is a workaround for EMAC silicon problem: *//* "Incorrect layer 3 (L3) checksum is inserted in the sent *//* IPv4 fragmented packets." *//* Description: *//* When automatic checksum insertion is enabled and the packet *//* is IPv4 frame fragment, then the MAC may incorrectly insert *//* checksum into the packet. This corrupts the payload data *//* and generates checksum errors at the receiver. */uint16_t prot = __UNALIGNED_UINT16_READ(&tx_desc[Emac.tx_index].Addr[12]);uint16_t frag = __UNALIGNED_UINT16_READ(&tx_desc[Emac.tx_index].Addr[20]);if ((prot == 0x0008) && (frag & 0xFF3F)) {/* Insert only IP header checksum in fragmented frame */ctrl |= DMA_TX_CIC_IP;}else {/* Insert IP header and payload checksums (TCP,UDP,ICMP) */ctrl |= DMA_TX_CIC;}} #endifctrl &= ~(DMA_TX_IC | DMA_TX_TTSE);if (flags & ARM_ETH_MAC_TX_FRAME_EVENT) { ctrl |= DMA_TX_IC; } #if (EMAC_TIME_STAMP != 0)if (flags & ARM_ETH_MAC_TX_FRAME_TIMESTAMP) { ctrl |= DMA_TX_TTSE; }Emac.tx_ts_index = Emac.tx_index; #endiftx_desc[Emac.tx_index].CtrlStat = ctrl | DMA_TX_OWN;Emac.tx_index++;if (Emac.tx_index == NUM_TX_BUF) { Emac.tx_index = 0U; }Emac.frame_end = NULL;/* 啟動幀傳輸 */ETH->DMASR = ETH_DMASR_TPSS;ETH->DMATPDR = 0U;return ARM_DRIVER_OK; }函數(shù)描述:
用于控制以太網(wǎng)幀數(shù)據(jù)的發(fā)送。此函數(shù)會將用戶要發(fā)送的數(shù)據(jù)存入到以太網(wǎng)DMA緩沖里面,而不必等待發(fā)送完成,只要有緩沖,就可以繼續(xù)往里面存數(shù)據(jù)。
函數(shù)參數(shù):
- ? 第1個參數(shù)是要發(fā)送的數(shù)據(jù)地址。
- ? 第2個參數(shù)是發(fā)送的字節(jié)數(shù)。
- ? 第3個參數(shù)支持的配置如下:
6.5.10 函數(shù)ReadFrame
函數(shù)原型:
static int32_t ReadFrame (uint8_t *frame, uint32_t len) {uint8_t const *src = rx_desc[Emac.rx_index].Addr;int32_t cnt = (int32_t)len;if ((frame == NULL) && (len != 0U)) {return ARM_DRIVER_ERROR_PARAMETER;}if ((Emac.flags & EMAC_FLAG_POWER) == 0U) {return ARM_DRIVER_ERROR;}/* 快速復(fù)制數(shù)據(jù)到幀緩沖 */for ( ; len > 7U; frame += 8, src += 8, len -= 8U) {__UNALIGNED_UINT32_WRITE(&frame[0], __UNALIGNED_UINT32_READ(&src[0]));__UNALIGNED_UINT32_WRITE(&frame[4], __UNALIGNED_UINT32_READ(&src[4]));}/* 復(fù)制剩余7字節(jié) */for ( ; len > 1U; frame += 2, src += 2, len -= 2U) {__UNALIGNED_UINT16_WRITE(&frame[0], __UNALIGNED_UINT16_READ(&src[0]));}if (len > 0U) { frame[0] = src[0]; }/* 設(shè)置此塊到ETH-DMA */rx_desc[Emac.rx_index].Stat = DMA_RX_OWN;Emac.rx_index++;if (Emac.rx_index == NUM_RX_BUF) { Emac.rx_index = 0; }if (ETH->DMASR & ETH_DMASR_RBUS) {/* 沒有緩沖,釋放 */ETH->DMASR = ETH_DMASR_RBUS;ETH->DMARPDR = 0;}return (cnt); }函數(shù)描述:
用于讀取以太網(wǎng)幀數(shù)據(jù)。
函數(shù)參數(shù):
- ? 第1個參數(shù)是讀取數(shù)據(jù)的存儲地址。
- ? 第2個參數(shù)存儲數(shù)據(jù)的緩沖大小。
- ? 返回值,返回數(shù)值大于0,表示讀取的字節(jié)數(shù),返回數(shù)值小于0表示出錯。
注意事項:
調(diào)用此函數(shù)前,需要先調(diào)用函數(shù)ARM_ETH_MAC_Control (ARM_ETH_MAC_CONTROL_RX , 1)使能接收。
6.5.11 函數(shù)GetRxFrameSize
函數(shù)原型:
static uint32_t GetRxFrameSize (void) {uint32_t stat = rx_desc[Emac.rx_index].Stat;if ((Emac.flags & EMAC_FLAG_POWER) == 0U) {return (0U);}if (stat & DMA_RX_OWN) {/* DMA使用中 */return (0U);}if (((stat & DMA_RX_ES) != 0) ||((stat & DMA_RX_FS) == 0) ||((stat & DMA_RX_LS) == 0)) {/* 錯誤,塊無效 */return (0xFFFFFFFFU);}return (((stat & DMA_RX_FL) >> 16) - 4U); }函數(shù)描述:
用于獲取接收到的幀大小,此函數(shù)會在ARM_ETH_MAC_ReadFrame之前被調(diào)用。
函數(shù)參數(shù):
- ? 返回值,返回接收到的數(shù)據(jù)大小。
注意事項:
幀大小包括MAC地址和接收到數(shù)據(jù)。此函數(shù)返回數(shù)值0表示接收緩沖區(qū)里面沒有數(shù)據(jù),如果接收到的數(shù)數(shù)據(jù)大于最大的幀大小或者小于最小的幀大小,都將被函數(shù)ARM_ETH_MAC_ReadFrame放棄。
6.5.12 函數(shù)GetRxFrameTime
函數(shù)原型:
static int32_t GetRxFrameTime (ARM_ETH_MAC_TIME *time) { #if (EMAC_TIME_STAMP)RX_Desc *rxd = &rx_desc[Emac.rx_index];if ((Emac.flags & EMAC_FLAG_POWER) == 0U) {return ARM_DRIVER_ERROR;}if (rxd->Stat & DMA_RX_OWN) {/* DMA使用中 */return ARM_DRIVER_ERROR_BUSY;}time->ns = rxd->TimeLo;time->sec = rxd->TimeHi;return ARM_DRIVER_OK; #else(void)time;return ARM_DRIVER_ERROR; #endif }函數(shù)描述:
用于獲取以太網(wǎng)接收幀時間戳。
函數(shù)參數(shù):
- ? 第1個參數(shù)用于存儲獲取的以太網(wǎng)發(fā)送幀時間戳。
- ? 回值,設(shè)置正確返回ARM_DRIVER_OK,設(shè)置錯誤返回ARM_DRIVER_ERROR,而ARM_DRIVER_ERROR_UNSUPPORTED表示不支持。
注意事項:
必須在調(diào)用函數(shù)ARM_ETH_MAC_ReadFrame前,調(diào)用此函數(shù)。
6.5.13 函數(shù)GetTxFrameSize
函數(shù)原型:
static int32_t GetTxFrameTime (ARM_ETH_MAC_TIME *time) { #if (EMAC_TIME_STAMP)TX_Desc *txd = &tx_desc[Emac.tx_ts_index];if ((Emac.flags & EMAC_FLAG_POWER) == 0U) {return ARM_DRIVER_ERROR;}if (txd->CtrlStat & DMA_RX_OWN) {/* DMA忙 */return ARM_DRIVER_ERROR_BUSY;}if ((txd->CtrlStat & DMA_TX_TTSS) == 0) {/* 驅(qū)動錯誤,發(fā)送時間戳不可用 */return ARM_DRIVER_ERROR;}time->ns = txd->TimeLo;time->sec = txd->TimeHi;return ARM_DRIVER_OK; #else(void)time;return ARM_DRIVER_ERROR; #endif }函數(shù)描述:
用于獲取以太網(wǎng)發(fā)送幀時間戳。
函數(shù)參數(shù):
- ? 第1個參數(shù)用于存儲返回的時間戳。
- ? 返回值,設(shè)置正確返回ARM_DRIVER_OK,設(shè)置錯誤返回ARM_DRIVER_ERROR,而ARM_DRIVER_ERROR_UNSUPPORTED表示不支持。
6.5.14 函數(shù)ControlTimer
函數(shù)原型:
static int32_t ControlTimer (uint32_t control, ARM_ETH_MAC_TIME *time) { #if (EMAC_TIME_STAMP != 0)if ((Emac.flags & EMAC_FLAG_POWER) == 0U) {return ARM_DRIVER_ERROR;}if ((control != ARM_ETH_MAC_TIMER_GET_TIME) && (control != ARM_ETH_MAC_TIMER_SET_TIME) && (control != ARM_ETH_MAC_TIMER_INC_TIME) && (control != ARM_ETH_MAC_TIMER_DEC_TIME) && (control != ARM_ETH_MAC_TIMER_SET_ALARM) && (control != ARM_ETH_MAC_TIMER_ADJUST_CLOCK)) {return ARM_DRIVER_ERROR_PARAMETER;}switch (control) {case ARM_ETH_MAC_TIMER_GET_TIME:/* 獲取當(dāng)前時間 */time->sec = ETH->PTPTSHR;time->ns = ETH->PTPTSLR;break;case ARM_ETH_MAC_TIMER_SET_TIME:/* 設(shè)置新時間*/ETH->PTPTSHUR = time->sec;ETH->PTPTSLUR = time->ns;/* 初始TS */ETH->PTPTSCR |= ETH_PTPTSCR_TSSTI;break;case ARM_ETH_MAC_TIMER_INC_TIME:/* 增加當(dāng)前時間 */ETH->PTPTSHUR = time->sec;ETH->PTPTSLUR = time->ns;/* 更新 */ETH->PTPTSCR |= ETH_PTPTSCR_TSSTU;break;case ARM_ETH_MAC_TIMER_DEC_TIME:/* 減少當(dāng)前時間 */ETH->PTPTSHUR = time->sec;ETH->PTPTSLUR = time->ns | 0x80000000U;/* 更新 */ETH->PTPTSCR |= ETH_PTPTSCR_TSSTU;break;case ARM_ETH_MAC_TIMER_SET_ALARM:/* 設(shè)置鬧鐘時間 */ETH->PTPTTHR = time->sec;ETH->PTPTTLR = time->ns;/* 使能PTP控制中的時間戳中斷 */ETH->PTPTSCR |= ETH_PTPTSCR_TSITE;if (time->sec || time->ns) {/* 使能時間戳觸發(fā)中斷 */ETH->MACIMR &= ~ETH_MACIMR_TSTIM;} else {/* 禁能時間戳觸發(fā)中斷 Disable */ETH->MACIMR |= ETH_MACIMR_TSTIM;}break;case ARM_ETH_MAC_TIMER_ADJUST_CLOCK:/* 調(diào)整當(dāng)前時間,精確校準(zhǔn) *//* 校準(zhǔn)因子Q31 (0x80000000 = 1.000000000) */ETH->PTPTSAR = (uint32_t)(((uint64_t)time->ns * ETH->PTPTSAR) >> 31);/* 精確的TS時鐘校準(zhǔn) */ETH->PTPTSCR |= ETH_PTPTSCR_TSARU;break;}return ARM_DRIVER_OK; #else(void)control;(void)time;return ARM_DRIVER_ERROR; #endif }函數(shù)描述:
高精度定時器控制。
函數(shù)參數(shù):
- ? 第1個參數(shù)是高精度定時器配置選項,支持的配置如下:
- ? 第2個參數(shù)設(shè)置時間。
- ? 返回值,設(shè)置正確返回ARM_DRIVER_OK,設(shè)置錯誤返回ARM_DRIVER_ERROR,而ARM_DRIVER_ERROR_UNSUPPORTED表示不支持。
6.5.15 函數(shù)Control
函數(shù)原型:
static int32_t Control (uint32_t control, uint32_t arg) {uint32_t maccr;uint32_t dmaomr;uint32_t macffr;if ((Emac.flags & EMAC_FLAG_POWER) == 0U) {return ARM_DRIVER_ERROR;}if ((control != ARM_ETH_MAC_CONFIGURE) && (control != ARM_ETH_MAC_CONTROL_TX) && (control != ARM_ETH_MAC_CONTROL_RX) && (control != ARM_ETH_MAC_FLUSH) && (control != ARM_ETH_MAC_SLEEP) && (control != ARM_ETH_MAC_VLAN_FILTER)) {return ARM_DRIVER_ERROR_PARAMETER;}switch (control) {case ARM_ETH_MAC_CONFIGURE:maccr = ETH->MACCR & ~(ETH_MACCR_FES | ETH_MACCR_DM |ETH_MACCR_LM | ETH_MACCR_IPCO);/* 配置100Mbps或者10Mbps模式 */switch (arg & ARM_ETH_MAC_SPEED_Msk) {case ARM_ETH_MAC_SPEED_10M: #if (ETH_MII == 0)/* RMII Half Duplex Colision detection does not work */maccr |= ETH_MACCR_DM; #endifbreak;case ARM_ETH_SPEED_100M:maccr |= ETH_MACCR_FES;break;default:return ARM_DRIVER_ERROR_UNSUPPORTED;}/* 配置全雙工或者半雙工模式 */switch (arg & ARM_ETH_MAC_DUPLEX_Msk) {case ARM_ETH_MAC_DUPLEX_FULL:maccr |= ETH_MACCR_DM;break;case ARM_ETH_MAC_DUPLEX_HALF:break;default:return ARM_DRIVER_ERROR;}/* 配置回環(huán)模式 */if (arg & ARM_ETH_MAC_LOOPBACK) {maccr |= ETH_MACCR_LM;}dmaomr = ETH->DMAOMR & ~(ETH_DMAOMR_RSF| ETH_DMAOMR_TSF); #if (EMAC_CHECKSUM_OFFLOAD != 0)/* 使能接收校驗和驗證 */if (arg & ARM_ETH_MAC_CHECKSUM_OFFLOAD_RX) {maccr |= ETH_MACCR_IPCO;dmaomr |= ETH_DMAOMR_RSF;}/* 使能發(fā)送校驗和產(chǎn)生 */if (arg & ARM_ETH_MAC_CHECKSUM_OFFLOAD_TX) {dmaomr |= ETH_DMAOMR_TSF;Emac.tx_cks_offload = true;}else {Emac.tx_cks_offload = false;} #elseif ((arg & ARM_ETH_MAC_CHECKSUM_OFFLOAD_RX) ||(arg & ARM_ETH_MAC_CHECKSUM_OFFLOAD_TX)) {/* 驅(qū)動程序禁止了硬件校驗和 */return ARM_DRIVER_ERROR;} #endifETH->DMAOMR = dmaomr;ETH->MACCR = maccr;macffr = ETH->MACFFR & ~(ETH_MACFFR_PM | ETH_MACFFR_PAM | ETH_MACFFR_BFD);/* 使能廣播幀接收 */if ((arg & ARM_ETH_MAC_ADDRESS_BROADCAST) == 0) {macffr |= ETH_MACFFR_BFD;}/* 使能組播幀接收 */if (arg & ARM_ETH_MAC_ADDRESS_MULTICAST) {macffr |= ETH_MACFFR_PAM;}/* 設(shè)置無過濾,所有幀都可以接收 */if (arg & ARM_ETH_MAC_ADDRESS_ALL) {macffr |= ETH_MACFFR_PM;}ETH->MACFFR = macffr;break;case ARM_ETH_MAC_CONTROL_TX:/* 使能或者禁止MAC發(fā)送 */maccr = ETH->MACCR & ~ETH_MACCR_TE;dmaomr = ETH->DMAOMR & ~ETH_DMAOMR_ST;if (arg != 0) {init_dma ();maccr |= ETH_MACCR_TE;dmaomr |= ETH_DMAOMR_ST;}ETH->MACCR = maccr;ETH->DMAOMR = dmaomr;break;case ARM_ETH_MAC_CONTROL_RX:/* 使能或者禁止MAC接收 */maccr = ETH->MACCR & ~ETH_MACCR_RE;dmaomr = ETH->DMAOMR & ~ETH_DMAOMR_SR;if (arg != 0) {init_dma ();maccr |= ETH_MACCR_RE;dmaomr |= ETH_DMAOMR_SR;}ETH->MACCR = maccr;ETH->DMAOMR = dmaomr;break;case ARM_ETH_MAC_FLUSH:/* 清空發(fā)送或者接收緩沖 */if (arg & ARM_ETH_MAC_FLUSH_RX) {}if (arg & ARM_ETH_MAC_FLUSH_TX) {ETH->DMAOMR |= ETH_DMAOMR_FTF;}break;case ARM_ETH_MAC_VLAN_FILTER:/* 配置VLAN過濾 */ETH->MACVLANTR = arg;break;}return ARM_DRIVER_OK; }函數(shù)描述:
用于MAC的配置
函數(shù)參數(shù):
- ? 第1個參數(shù)支持的配置如下
- ? 第2個參數(shù)針對第1個參數(shù)做的具體配置。
- ? ARM_ETH_MAC_CONFIGURE 支持的配置:
-
- ? ARM_ETH_MAC_CONTROL_TX
0表示禁止發(fā)送,1表示使能發(fā)送。
-
- ? ARM_ETH_MAC_CONTROL_RX
0表示禁止接收,1表示使能接收。
-
- ? ARM_ETH_MAC_FLUSH支持的配置:
ARM_ETH_MAC_FLUSH_RX 表示接收清空。?????
ARM_ETH_MAC_FLUSH_TX 表示發(fā)送清空。
-
- ? VLAN濾波器支持的配置:
6.5.16 函數(shù)PHY_Read
函數(shù)原型:
static int32_t PHY_Read (uint8_t phy_addr, uint8_t reg_addr, uint16_t *data) {uint32_t val, tick;if ((Emac.flags & EMAC_FLAG_POWER) == 0U) {return ARM_DRIVER_ERROR;}val = ETH->MACMIIAR & ETH_MACMIIAR_CR;ETH->MACMIIAR = val | ETH_MACMIIAR_MB | ((uint32_t)phy_addr << 11) |((uint32_t)reg_addr << 6) ;/* 等待操作完成 */tick = HAL_GetTick();do {if ((ETH->MACMIIAR & ETH_MACMIIAR_MB) == 0U) { break; }} while ((HAL_GetTick() - tick) < PHY_TIMEOUT);if ((ETH->MACMIIAR & ETH_MACMIIAR_MB) == 0U) {*data = ETH->MACMIIDR & ETH_MACMIIDR_MD;return ARM_DRIVER_OK;}return ARM_DRIVER_ERROR_TIMEOUT; }函數(shù)描述:
用于以太網(wǎng)PHY芯片的讀操作。
函數(shù)參數(shù):
- ? 第1個參數(shù)是PHY地址。
- ? 第2個參數(shù)是寄存器地址。
- ? 第3個參數(shù)是寄存器寫入的數(shù)據(jù)。
- ? 返回值,操作正確返回ARM_DRIVER_OK,操作錯誤返回ARM_DRIVER_ERROR。
6.5.17 函數(shù)PHY_Write
函數(shù)原型:
static int32_t PHY_Write (uint8_t phy_addr, uint8_t reg_addr, uint16_t data) {uint32_t val, tick;if ((Emac.flags & EMAC_FLAG_POWER) == 0U) {return ARM_DRIVER_ERROR;}ETH->MACMIIDR = data;val = ETH->MACMIIAR & ETH_MACMIIAR_CR;ETH->MACMIIAR = val | ETH_MACMIIAR_MB | ETH_MACMIIAR_MW | ((uint32_t)phy_addr << 11) |((uint32_t)reg_addr << 6) ;/* 等待操作完成 */tick = HAL_GetTick();do {if ((ETH->MACMIIAR & ETH_MACMIIAR_MB) == 0U) { break; }} while ((HAL_GetTick() - tick) < PHY_TIMEOUT);if ((ETH->MACMIIAR & ETH_MACMIIAR_MB) == 0U) {return ARM_DRIVER_OK;}return ARM_DRIVER_ERROR_TIMEOUT; }函數(shù)描述:
用于以太網(wǎng)PHY芯片的寫操作。
函數(shù)參數(shù):
- ? 第1個參數(shù)是PHY地址。
- ? 第2個參數(shù)是寄存器地址。
- ? 第3個參數(shù)是寄存器寫入的數(shù)據(jù)。
- ? 返回值,操作正確返回ARM_DRIVER_OK,操作錯誤返回ARM_DRIVER_ERROR。
6.6?? 總結(jié)
本章節(jié)就為大家講解這么多,主要是為學(xué)習(xí)下個章節(jié)RL-TCPnet的移植做準(zhǔn)備。學(xué)完本章后,務(wù)必將STM32參考手冊中MAC章節(jié)讀一遍。
?
總結(jié)
以上是生活随笔為你收集整理的【STM32F429】第6章 RL-TCPnet V7.X底层驱动说明的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: JPG怎么转TXT
- 下一篇: (数学建模)6.1灰色系统理论与灰色关联