/** * \file emac.c * * \brief EMAC APIs. * * This file contains the device abstraction layer APIs for EMAC. */ /* * Copyright (C) 2009-2018 Texas Instruments Incorporated - www.ti.com * * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the * distribution. * * Neither the name of Texas Instruments Incorporated nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ /* USER CODE BEGIN (0) */ /* USER CODE END */ #include "emac.h" #include "sys_vim.h" /* USER CODE BEGIN (1) */ /* USER CODE END */ /* Defining interface for all the emac instances */ hdkif_t hdkif_data[MAX_EMAC_INSTANCE]; /*SAFETYMCUSW 25 D MR:8.7 "Statically allocated memory needs to be available to entire application." */ static uint8_t pbuf_array[MAX_RX_PBUF_ALLOC][MAX_TRANSFER_UNIT]; /******************************************************************************* * INTERNAL MACRO DEFINITIONS *******************************************************************************/ #define EMAC_CONTROL_RESET (0x01U) #define EMAC_SOFT_RESET (0x01U) #define EMAC_MAX_HEADER_DESC (8U) #define EMAC_UNICAST_DISABLE (0xFFU) /******************************************************************************* * API FUNCTION DEFINITIONS *******************************************************************************/ /** * \brief Enables the TXPULSE Interrupt Generation. * * \param emacBase Base address of the EMAC Module registers. * \param emacCtrlBase Base address of the EMAC CONTROL module registers * \param ctrlCore Channel number for which the interrupt to be enabled in EMAC Control module * \param channel Channel number for which interrupt to be enabled * * \return None * **/ /* SourceId : ETH_SourceId_001 */ /* DesignId : ETH_DesignId_001*/ /* Requirements : HL_ETH_SR15 */ void EMACTxIntPulseEnable(uint32 emacBase, uint32 emacCtrlBase, uint32 ctrlCore, uint32 channel) { HWREG(emacBase + EMAC_TXINTMASKSET) |= ((uint32)1U << channel); HWREG(emacCtrlBase + EMAC_CTRL_CnTXEN(ctrlCore)) |= ((uint32)1U << channel); } /** * \brief Disables the TXPULSE Interrupt Generation. * * \param emacBase Base address of the EMAC Module registers. * \param emacCtrlBase Base address of the EMAC CONTROL module registers * \param ctrlCore Channel number for which the interrupt to be enabled in EMAC Control module * \param channel Channel number for which interrupt to be disabled * * \return None * **/ /* SourceId : ETH_SourceId_002 */ /* DesignId : ETH_DesignId_002*/ /* Requirements : HL_ETH_SR15 */ void EMACTxIntPulseDisable(uint32 emacBase, uint32 emacCtrlBase, uint32 ctrlCore, uint32 channel) /*SAFETYMCUSW 1 J MR:14.1 "LDRA Tool issue." */ { HWREG(emacBase + EMAC_TXINTMASKCLEAR) |= ((uint32)1U << channel); HWREG(emacCtrlBase + EMAC_CTRL_CnTXEN(ctrlCore)) &= (~((uint32)1U << channel)); } /** * \brief Enables the RXPULSE Interrupt Generation. * * \param emacBase Base address of the EMAC Module registers. * \param emacCtrlBase Base address of the EMAC CONTROL module registers * \param ctrlCore Control core for which the interrupt to be enabled. * \param channel Channel number for which interrupt to be enabled * * \return None * **/ /* SourceId : ETH_SourceId_003 */ /* DesignId : ETH_DesignId_003*/ /* Requirements : HL_ETH_SR15 */ void EMACRxIntPulseEnable(uint32 emacBase, uint32 emacCtrlBase, uint32 ctrlCore, uint32 channel) /*SAFETYMCUSW 1 J MR:14.1 "LDRA Tool issue." */ { HWREG(emacBase + EMAC_RXINTMASKSET) |= ((uint32)1U << channel); HWREG(emacCtrlBase + EMAC_CTRL_CnRXEN(ctrlCore)) |= ((uint32)1U << channel); } /** * \brief Disables the RXPULSE Interrupt Generation. * * \param emacBase Base address of the EMAC Module registers. * \param emacCtrlBase Base address of the EMAC CONTROL module registers * \param ctrlCore Control core for which the interrupt to be disabled. * \param channel Channel number for which interrupt to be disabled * * \return None * **/ /* SourceId : ETH_SourceId_004 */ /* DesignId : ETH_DesignId_004*/ /* Requirements : HL_ETH_SR15 */ void EMACRxIntPulseDisable(uint32 emacBase, uint32 emacCtrlBase, uint32 ctrlCore, uint32 channel) { HWREG(emacBase + EMAC_RXINTMASKCLEAR) |= ((uint32)1U << channel); HWREG(emacCtrlBase + EMAC_CTRL_CnRXEN(ctrlCore)) &= (~((uint32)1U << channel)); } /** * \brief This API sets the RMII speed. The RMII Speed can be 10 Mbps or * 100 Mbps * * \param emacBase Base address of the EMAC Module registers. * \param speed speed for setting. * speed can take the following values. \n * EMAC_RMIISPEED_10MBPS - 10 Mbps \n * EMAC_RMIISPEED_100MBPS - 100 Mbps. * * \return None * **/ /* SourceId : ETH_SourceId_005 */ /* DesignId : ETH_DesignId_005*/ /* Requirements : HL_ETH_SR19 */ void EMACRMIISpeedSet(uint32 emacBase, uint32 speed) { HWREG(emacBase + EMAC_MACCONTROL) &= (~(uint32)EMAC_MACCONTROL_RMIISPEED); HWREG(emacBase + EMAC_MACCONTROL) |= speed; } /* SourceId : ETH_SourceId_006 */ /* DesignId : ETH_DesignId_006*/ /* Requirements : HL_ETH_SR18 */ /** * \brief This API set the GMII bit, RX and TX are enabled for receive and transmit. * Note: This is not the API to enable MII. * \param emacBase Base address of the EMAC Module registers. * * \return None * **/ void EMACMIIEnable(uint32 emacBase) { HWREG(emacBase + EMAC_MACCONTROL) |= EMAC_MACCONTROL_GMIIEN; } /** * \brief This API clears the GMII bit, Rx and Tx are held in reset. * Note: This is not the API to disable MII. * \param emacBase Base address of the EMAC Module registers. * * \return None * **/ /* SourceId : ETH_SourceId_007 */ /* DesignId : ETH_DesignId_007*/ /* Requirements : HL_ETH_SR18 */ void EMACMIIDisable(uint32 emacBase) /*SAFETYMCUSW 1 J MR:14.1 "LDRA Tool issue." */ { HWREG(emacBase + EMAC_MACCONTROL) &= (~(uint32)EMAC_MACCONTROL_GMIIEN); } /** * \brief This API sets the duplex mode of operation(full/half) for MAC. * * \param emacBase Base address of the EMAC Module registers. * \param duplexMode duplex mode of operation. * duplexMode can take the following values. \n * EMAC_DUPLEX_FULL - Full Duplex \n * EMAC_DUPLEX_HALF - Half Duplex. * * \return None * **/ /* SourceId : ETH_SourceId_008 */ /* DesignId : ETH_DesignId_008*/ /* Requirements : HL_ETH_SR21 */ void EMACDuplexSet(uint32 emacBase, uint32 duplexMode) { HWREG(emacBase + EMAC_MACCONTROL) &= (~(uint32)EMAC_MACCONTROL_FULLDUPLEX); HWREG(emacBase + EMAC_MACCONTROL) |= duplexMode; } /** * \brief API to enable the transmit in the TX Control Register * After the transmit is enabled, any write to TXHDP of * a channel will start transmission * * \param emacBase Base Address of the EMAC Module Registers. * * \return None * **/ /* SourceId : ETH_SourceId_009 */ /* DesignId : ETH_DesignId_009*/ /* Requirements : HL_ETH_SR21 */ void EMACTxEnable(uint32 emacBase) { HWREG(emacBase + EMAC_TXCONTROL) = EMAC_TXCONTROL_TXEN; } /** * \brief API to disable the transmit in the TX Control Register * * \param emacBase Base Address of the EMAC Module Registers. * * \return None * **/ /* SourceId : ETH_SourceId_010 */ /* DesignId : ETH_DesignId_010*/ /* Requirements : HL_ETH_SR21 */ void EMACTxDisable(uint32 emacBase) /*SAFETYMCUSW 1 J MR:14.1 "LDRA Tool issue." */ { HWREG(emacBase + EMAC_TXCONTROL) = EMAC_TXCONTROL_TXDIS; } /** * \brief API to enable the receive in the RX Control Register * After the receive is enabled, and write to RXHDP of * a channel, the data can be received in the destination * specified by the corresponding RX buffer descriptor. * * \param emacBase Base Address of the EMAC Module Registers. * * \return None * **/ /* SourceId : ETH_SourceId_011*/ /* DesignId : ETH_DesignId_011*/ /* Requirements : HL_ETH_SR21 */ void EMACRxEnable(uint32 emacBase) { HWREG(emacBase + EMAC_RXCONTROL) = EMAC_RXCONTROL_RXEN; } /** * \brief API to disable the receive in the RX Control Register * * \param emacBase Base Address of the EMAC Module Registers. * * \return None * **/ /* SourceId : ETH_SourceId_012*/ /* DesignId : ETH_DesignId_012*/ /* Requirements : HL_ETH_SR21 */ void EMACRxDisable(uint32 emacBase) /*SAFETYMCUSW 1 J MR:14.1 "LDRA Tool issue." */ { HWREG(emacBase + EMAC_RXCONTROL) = EMAC_RXCONTROL_RXDIS; } /** * \brief API to write the TX HDP register. If transmit is enabled, * write to the TX HDP will immediately start transmission. * The data will be taken from the buffer pointer of the TX buffer * descriptor written to the TX HDP * * \param emacBase Base Address of the EMAC Module Registers.\n * \param descHdr Address of the TX buffer descriptor * \param channel Channel Number * * \return None * **/ /* SourceId : ETH_SourceId_013*/ /* DesignId : ETH_DesignId_013*/ /* Requirements : HL_ETH_SR16 */ void EMACTxHdrDescPtrWrite(uint32 emacBase, uint32 descHdr, uint32 channel) { HWREG(emacBase + EMAC_TXHDP(channel)) = descHdr; } /** * \brief API to write the RX HDP register. If receive is enabled, * write to the RX HDP will enable data reception to point to * the corresponding RX buffer descriptor's buffer pointer. * * \param emacBase Base Address of the EMAC Module Registers.\n * \param descHdr Address of the RX buffer descriptor * \param channel Channel Number * * \return None * **/ /* SourceId : ETH_SourceId_014 */ /* DesignId : ETH_DesignId_014*/ /* Requirements : HL_ETH_SR16 */ void EMACRxHdrDescPtrWrite(uint32 emacBase, uint32 descHdr, uint32 channel) { HWREG(emacBase + EMAC_RXHDP(channel)) = descHdr; } /** * \brief This API Initializes the EMAC and EMAC Control modules. The * EMAC Control module is reset, the CPPI RAM is cleared. also, * all the interrupts are disabled. This API does not enable any * interrupt or operation of the EMAC. * * \param emacCtrlBase Base Address of the EMAC Control module * registers.\n * \param emacBase Base address of the EMAC module registers * * \return None * **/ /* SourceId : ETH_SourceId_015 */ /* DesignId : ETH_DesignId_015*/ /* Requirements : HL_ETH_SR6 */ void EMACInit(uint32 emacCtrlBase, uint32 emacBase) { uint32 cnt; /* Reset the EMAC Control Module. This clears the CPPI RAM also */ HWREG(emacCtrlBase + EMAC_CTRL_SOFTRESET) = EMAC_CONTROL_RESET; /*SAFETYMCUSW 28 D MR:NA "Hardware status bit read check" */ while((HWREG(emacCtrlBase + EMAC_CTRL_SOFTRESET) & EMAC_CONTROL_RESET) == EMAC_CONTROL_RESET) { } /* Wait */ /* Reset the EMAC Module. This clears the CPPI RAM also */ HWREG(emacBase + EMAC_SOFTRESET) = EMAC_SOFT_RESET; /*SAFETYMCUSW 28 D MR:NA "Hardware status bit read check" */ while((HWREG(emacBase + EMAC_SOFTRESET) & EMAC_SOFT_RESET) == EMAC_SOFT_RESET ) { } /* Wait */ HWREG(emacBase + EMAC_MACCONTROL)= 0U; HWREG(emacBase + EMAC_RXCONTROL)= 0U; HWREG(emacBase + EMAC_TXCONTROL)= 0U; /* Initialize all the header descriptor pointer registers */ for(cnt = 0U; cnt< EMAC_MAX_HEADER_DESC; cnt++) { HWREG(emacBase + EMAC_RXHDP(cnt)) = 0U; HWREG(emacBase + EMAC_TXHDP(cnt)) = 0U; HWREG(emacBase + EMAC_RXCP(cnt)) = 0U; HWREG(emacBase + EMAC_TXCP(cnt)) = 0U; HWREG(emacBase + EMAC_RXFREEBUFFER(cnt)) = 0xFFU; } /* Clear the interrupt enable for all the channels */ HWREG(emacBase + EMAC_TXINTMASKCLEAR) = 0xFFU; HWREG(emacBase + EMAC_RXINTMASKCLEAR) = 0xFFU; HWREG(emacBase + EMAC_MACHASH1) = 0U; HWREG(emacBase + EMAC_MACHASH2) = 0U; HWREG(emacBase + EMAC_RXBUFFEROFFSET) = 0U; } /** * \brief Sets the MAC Address in MACSRCADDR registers. * * \param emacBase Base Address of the EMAC module registers. * \param macAddr Start address of a MAC address array. * The array[0] shall be the LSB of the MAC address * * \return None * **/ /* SourceId : ETH_SourceId_016 */ /* DesignId : ETH_DesignId_016*/ /* Requirements : HL_ETH_SR7 */ void EMACMACSrcAddrSet(uint32 emacBase, uint8 macAddr[6]) { HWREG(emacBase + EMAC_MACSRCADDRHI) = ((uint32)macAddr[5U] |((uint32)macAddr[4U] << 8U) |((uint32)macAddr[3U] << 16U) |((uint32)macAddr[2U] << 24U)); HWREG(emacBase + EMAC_MACSRCADDRLO) = ((uint32)macAddr[1U] | ((uint32)macAddr[0U] << 8U)); } /** * \brief Sets the MAC Address in MACADDR registers. * * \param emacBase Base Address of the EMAC module registers. * \param channel Channel Number * \param matchFilt Match or Filter * \param macAddr Start address of a MAC address array. * The array[0] shall be the LSB of the MAC address * matchFilt can take the following values \n * EMAC_MACADDR_NO_MATCH_NO_FILTER - Address is not used to match * or filter incoming packet. \n * EMAC_MACADDR_FILTER - Address is used to filter incoming packets \n * EMAC_MACADDR_MATCH - Address is used to match incoming packets \n * * \return None * **/ /* SourceId : ETH_SourceId_017 */ /* DesignId : ETH_DesignId_017*/ /* Requirements : HL_ETH_SR7 */ void EMACMACAddrSet(uint32 emacBase, uint32 channel, uint8 macAddr[6], uint32 matchFilt) { HWREG(emacBase + EMAC_MACINDEX) = channel; HWREG(emacBase + EMAC_MACADDRHI) = ((uint32)macAddr[5U] |((uint32)macAddr[4U] << 8U) |((uint32)macAddr[3U] << 16U) |((uint32)macAddr[2U] << 24U)); HWREG(emacBase + EMAC_MACADDRLO) = ((uint32)macAddr[1U] | ((uint32)macAddr[0U] << 8U) | matchFilt | (channel << 16U)); } /** * \brief Acknowledges an interrupt processed to the EMAC Control Core. * * \param emacBase Base Address of the EMAC module registers. * \param eoiFlag Type of interrupt to acknowledge to the EMAC Control * module. * eoiFlag can take the following values \n * EMAC_INT_CORE0_TX - Core 0 TX Interrupt * EMAC_INT_CORE1_TX - Core 1 TX Interrupt * EMAC_INT_CORE2_TX - Core 2 TX Interrupt * EMAC_INT_CORE0_RX - Core 0 RX Interrupt * EMAC_INT_CORE1_RX - Core 1 RX Interrupt * EMAC_INT_CORE2_RX - Core 2 RX Interrupt * \return None * **/ /* SourceId : ETH_SourceId_018 */ /* DesignId : ETH_DesignId_018*/ /* Requirements : HL_ETH_SR15 */ void EMACCoreIntAck(uint32 emacBase, uint32 eoiFlag) { /* Acknowledge the EMAC Control Core */ HWREG(emacBase + EMAC_MACEOIVECTOR) = eoiFlag; } /** * \brief Writes the the TX Completion Pointer for a specific channel * * \param emacBase Base Address of the EMAC module registers. * \param channel Channel Number. * \param comPtr Completion Pointer Value to be written * * \return None * **/ /* SourceId : ETH_SourceId_019 */ /* DesignId : ETH_DesignId_019*/ /* Requirements : HL_ETH_SR27 */ void EMACTxCPWrite(uint32 emacBase, uint32 channel, uint32 comPtr) { HWREG(emacBase + EMAC_TXCP(channel)) = comPtr; } /** * \brief Writes the the RX Completion Pointer for a specific channel * * \param emacBase Base Address of the EMAC module registers. * \param channel Channel Number. * \param comPtr Completion Pointer Value to be written * * \return None * **/ /* SourceId : ETH_SourceId_020 */ /* DesignId : ETH_DesignId_020*/ /* Requirements : HL_ETH_SR27 */ void EMACRxCPWrite(uint32 emacBase, uint32 channel, uint32 comPtr) { HWREG(emacBase + EMAC_RXCP(channel)) = comPtr; } /** * \brief Enables a specific channel to receive broadcast frames * * \param emacBase Base Address of the EMAC module registers. * \param channel Channel Number. * * \return None * **/ /* SourceId : ETH_SourceId_021 */ /* DesignId : ETH_DesignId_021*/ /* Requirements : HL_ETH_SR28 */ void EMACRxBroadCastEnable(uint32 emacBase, uint32 channel) { HWREG(emacBase + EMAC_RXMBPENABLE) &= (~(uint32)EMAC_RXMBPENABLE_RXBROADCH); HWREG(emacBase + EMAC_RXMBPENABLE) |= ((uint32)EMAC_RXMBPENABLE_RXBROADEN | ((uint32)channel << (uint32)EMAC_RXMBPENABLE_RXBROADCH_SHIFT)); } /** * \brief Disables a specific channel to receive broadcast frames * * \param emacBase Base Address of the EMAC module registers. * \param channel Channel Number. * * \return None * **/ /* SourceId : ETH_SourceId_022 */ /* DesignId : ETH_DesignId_022*/ /* Requirements : HL_ETH_SR28 */ void EMACRxBroadCastDisable(uint32 emacBase, uint32 channel) /*SAFETYMCUSW 1 J MR:14.1 "LDRA Tool issue." */ { HWREG(emacBase + EMAC_RXMBPENABLE) &= (~(uint32)EMAC_RXMBPENABLE_RXBROADCH); /* Broadcast Frames are filtered. */ HWREG(emacBase + EMAC_RXMBPENABLE) &= (~(uint32)EMAC_RXMBPENABLE_RXBROADEN); } /** * \brief Enables a specific channel to receive multicast frames * * \param emacBase Base Address of the EMAC module registers. * \param channel Channel Number. * * \return None * **/ /* SourceId : ETH_SourceId_023 */ /* DesignId : ETH_DesignId_023*/ /* Requirements : HL_ETH_SR28 */ void EMACRxMultiCastEnable(uint32 emacBase, uint32 channel) { HWREG(emacBase + EMAC_RXMBPENABLE) &= (~(uint32)EMAC_RXMBPENABLE_RXMULTCH); HWREG(emacBase + EMAC_RXMBPENABLE) |= ((uint32)EMAC_RXMBPENABLE_RXMULTEN |(channel)); } /** * \brief Disables a specific channel to receive multicast frames * * \param emacBase Base Address of the EMAC module registers. * \param channel Channel Number. * * \return None * **/ /* SourceId : ETH_SourceId_024 */ /* DesignId : ETH_DesignId_024*/ /* Requirements : HL_ETH_SR28 */ void EMACRxMultiCastDisable(uint32 emacBase, uint32 channel) { HWREG(emacBase + EMAC_RXMBPENABLE) &= (~(uint32)EMAC_RXMBPENABLE_RXMULTCH); HWREG(emacBase + EMAC_RXMBPENABLE) &= (~(uint32)EMAC_RXMBPENABLE_RXMULTEN); } /** * \brief Enables unicast for a specific channel * * \param emacBase Base Address of the EMAC module registers. * \param channel Channel Number. * * \return None * **/ /* SourceId : ETH_SourceId_025 */ /* DesignId : ETH_DesignId_025*/ /* Requirements : HL_ETH_SR14 */ void EMACRxUnicastSet(uint32 emacBase, uint32 channel) { HWREG(emacBase + EMAC_RXUNICASTSET) |= ((uint32)1U << channel); } /** * \brief Disables unicast for a specific channel * * \param emacBase Base Address of the EMAC module registers. * \param channel Channel Number. * * \return None * **/ /* SourceId : ETH_SourceId_026 */ /* DesignId : ETH_DesignId_026*/ /* Requirements : HL_ETH_SR14 */ void EMACRxUnicastClear(uint32 emacBase, uint32 channel) /*SAFETYMCUSW 1 J MR:14.1 "LDRA Tool issue." */ { HWREG(emacBase + EMAC_RXUNICASTCLEAR) |= ((uint32)1U << channel); } /** * \brief Set the free buffers for a specific channel * * \param emacBase Base Address of the EMAC module registers. * \param channel Channel Number. * \param nBuf Number of free buffers * * \return None * **/ /* SourceId : ETH_SourceId_027 */ /* DesignId : ETH_DesignId_027*/ /* Requirements : HL_ETH_SR20 */ void EMACNumFreeBufSet(uint32 emacBase, uint32 channel, uint32 nBuf) { HWREG(emacBase + EMAC_RXFREEBUFFER(channel)) = nBuf; } /** * \brief Gets the interrupt vectors of EMAC, which are pending * * \param emacBase Base Address of the EMAC module registers. * * \return Vectors * **/ /* SourceId : ETH_SourceId_028 */ /* DesignId : ETH_DesignId_028*/ /* Requirements : HL_ETH_SR15 */ uint32 EMACIntVectorGet(uint32 emacBase) { return (HWREG(emacBase + EMAC_MACINVECTOR)); } /** * Function to setup the instance parameters inside the interface * @param hdkif Network interface structure * @return none. */ /* SourceId : ETH_SourceId_029 */ /* DesignId : ETH_DesignId_029*/ /* Requirements : HL_ETH_SR6 */ void EMACInstConfig(hdkif_t *hdkif) { hdkif->emac_base = EMAC_0_BASE; hdkif->emac_ctrl_base = EMAC_CTRL_0_BASE; hdkif->emac_ctrl_ram = EMAC_CTRL_RAM_0_BASE; hdkif->mdio_base = MDIO_BASE; hdkif->phy_addr = 1U; /* (MISRA-C:2004 10.1/R) MISRA error reported with Code Composer Studio MISRA checker. */ hdkif->phy_autoneg = &Dp83640AutoNegotiate; hdkif->phy_partnerability = &Dp83640PartnerAbilityGet; } /** * Function to setup the link. AutoNegotiates with the phy for link * setup and set the EMAC with the result of autonegotiation. * @param hdkif Network interface structure. * @return ERR_OK if everything passed * others if not passed */ /* SourceId : ETH_SourceId_030 */ /* DesignId : ETH_DesignId_030*/ /* Requirements : HL_ETH_SR6 */ uint32 EMACLinkSetup(hdkif_t *hdkif) { uint32 linkstat = EMAC_ERR_CONNECT; uint16 partnr_ablty = 0U; uint32 phyduplex = EMAC_DUPLEX_HALF; volatile uint32 delay = 0xFFFFFU; if(Dp83640AutoNegotiate((uint32)hdkif->mdio_base, (uint32)hdkif->phy_addr, (uint16)((uint16)DP83640_100BTX | (uint16)DP83640_100BTX_FD | (uint16)DP83640_10BT | (uint16)DP83640_10BT_FD)) == TRUE) { linkstat = EMAC_ERR_OK; /* (MISRA-C:2004 10.1/R) MISRA error reported with Code Composer Studio MISRA checker (due to use of & ?) */ (void)Dp83640PartnerAbilityGet(hdkif->mdio_base, hdkif->phy_addr, &partnr_ablty); /* Check for 100 Mbps and duplex capability */ if((partnr_ablty & DP83640_100BTX_FD) != 0U) { phyduplex = EMAC_DUPLEX_FULL; } } else { linkstat = EMAC_ERR_CONNECT; } /* Set the EMAC with the negotiation results if it is successful */ if(linkstat == EMAC_ERR_OK) { EMACDuplexSet(hdkif->emac_base, phyduplex); } /* Wait for the MII to settle down */ /*SAFETYMCUSW 134 S MR:12.2 "LDRA Tool issue" */ while(delay != 0U) { delay--; } return linkstat; } /** * \brief Perform a transmit queue teardown, that is, transmission is aborted. * * \param emacBase Base Address of the EMAC module registers. * \param channel Channel Number. * * \return None * **/ /* SourceId : ETH_SourceId_031 */ /* DesignId : ETH_DesignId_031*/ /* Requirements : HL_ETH_SR22 */ void EMACTxTeardown(uint32 emacBase, uint32 channel) { HWREG(emacBase + EMAC_TXTEARDOWN) &= (channel); } /** * \brief Perform a receive queue teardown, that is, reception is aborted. * * \param emacBase Base Address of the EMAC module registers. * \param channel Channel Number. * * \return None * **/ /* SourceId : ETH_SourceId_032 */ /* DesignId : ETH_DesignId_032*/ /* Requirements : HL_ETH_SR22 */ void EMACRxTeardown(uint32 emacBase, uint32 channel) { HWREG(emacBase + EMAC_RXTEARDOWN) &= (channel); } /** * \brief Perform multicast frame filtering using the MAC Hash Registers. * * \param emacBase Base Address of the EMAC module registers. * \param hashTable The hash table which specifies which bits are to be accepted. * * \return None * **/ /* SourceId : ETH_SourceId_033 */ /* DesignId : ETH_DesignId_033*/ /* Requirements : HL_ETH_SR24 */ void EMACFrameSelect(uint32 emacBase, uint64 hashTable) { HWREG(emacBase + EMAC_MACHASH1) = (uint32)(hashTable & 0xFFFFFFFFU); HWREG(emacBase + EMAC_MACHASH2) = (uint32)(hashTable >> 32U); } /** * \brief Sets the Transmit Queue Priority type in the MACCONTROL Register * * \param emacBase Base Address of the EMAC module registers. * \param txPType The Transmit Queue Priority Type. * 0 results in a round-robin scheme being used to select the next channel, while 1 results * in a fixed-priority scheme( channel 7 highest priority). * * \return None * **/ /* SourceId : ETH_SourceId_034 */ /* DesignId : ETH_DesignId_034*/ /* Requirements : HL_ETH_SR25 */ void EMACTxPrioritySelect(uint32 emacBase, uint32 txPType) { /* 1- The queue uses a fixed-priority (channel 7 highest priority) scheme */ if(txPType == 1U) { HWREG(emacBase + EMAC_MACCONTROL) &= (~(uint32)(EMAC_MACCONTROL_TXPTYPE)); HWREG(emacBase + EMAC_MACCONTROL) |= EMAC_MACCONTROL_TXPTYPE; } else { HWREG(emacBase + EMAC_MACCONTROL) &= (~(uint32)(EMAC_MACCONTROL_TXPTYPE)); } } /** * \brief Performs a soft reset of the EMAC and EMAC Control Modules. * * \param emacCtrlBase Base address of the EMAC CONTROL module registers * \param emacBase Base Address of the EMAC module registers. * \return None * **/ /* SourceId : ETH_SourceId_035 */ /* DesignId : ETH_DesignId_035*/ /* Requirements : HL_ETH_SR26 */ void EMACSoftReset(uint32 emacCtrlBase, uint32 emacBase) { /* Reset the EMAC Control Module. This clears the CPPI RAM also */ HWREG(emacCtrlBase + EMAC_CTRL_SOFTRESET) = EMAC_CONTROL_RESET; /*SAFETYMCUSW 28 D MR:NA "Hardware status bit read check" */ while((HWREG(emacCtrlBase + EMAC_CTRL_SOFTRESET) & EMAC_CONTROL_RESET) == EMAC_CONTROL_RESET) { /* Wait for the reset to complete */ } /* Reset the EMAC Module. */ HWREG(emacBase + EMAC_SOFTRESET) = EMAC_SOFT_RESET; /*SAFETYMCUSW 28 D MR:NA "Hardware status bit read check" */ while((HWREG(emacBase + EMAC_SOFTRESET) & EMAC_SOFT_RESET) == EMAC_SOFT_RESET ) { /* Wait for the Reset to complete */ } } /** * \brief Enable Idle State of the EMAC Module. * * \param emacBase Base Address of the EMAC module registers. * \return None * **/ /* SourceId : ETH_SourceId_036 */ /* DesignId : ETH_DesignId_036*/ /* Requirements : HL_ETH_SR32 */ void EMACEnableIdleState(uint32 emacBase) { HWREG(emacBase + EMAC_MACCONTROL) |= EMAC_MACCONTROL_CMDIDLE; } /** * \brief Disable Idle State of the EMAC Module. * * \param emacBase Base Address of the EMAC module registers. * \return None * **/ /* SourceId : ETH_SourceId_037 */ /* DesignId : ETH_DesignId_037*/ /* Requirements : HL_ETH_SR32 */ void EMACDisableIdleState(uint32 emacBase) { HWREG(emacBase + EMAC_MACCONTROL) &= (~(uint32)(EMAC_MACCONTROL_CMDIDLE)); } /** * \brief Enables Loopback Mode. * * \param emacBase Base Address of the EMAC module registers. * \return None * **/ /* SourceId : ETH_SourceId_038 */ /* DesignId : ETH_DesignId_038*/ /* Requirements : HL_ETH_SR50 */ void EMACEnableLoopback(uint32 emacBase) /*SAFETYMCUSW 1 J MR:14.1 "LDRA Tool issue." */ { uint32 GMIIENval=0U; /*Store the value of GMIIEN bit before deasserting it */ GMIIENval = HWREG(emacBase + EMAC_MACCONTROL) & EMAC_MACCONTROL_GMIIEN; HWREG(emacBase + EMAC_MACCONTROL) &= (~(uint32)EMAC_MACCONTROL_GMIIEN); /*Enable Loopback */ HWREG(emacBase + EMAC_MACCONTROL) |= EMAC_MACCONTROL_LOOPBACK; /*Restore the value of GMIIEN bit */ HWREG(emacBase + EMAC_MACCONTROL) |= GMIIENval; } /** * \brief Disables Loopback Mode. * * \param emacBase Base Address of the EMAC module registers. * \return None * **/ /* SourceId : ETH_SourceId_039 */ /* DesignId : ETH_DesignId_039*/ /* Requirements : HL_ETH_SR50 */ void EMACDisableLoopback(uint32 emacBase) { uint32 GMIIENval=0U; /*Store the value of GMIIEN bit before deasserting it */ GMIIENval = HWREG(emacBase + EMAC_MACCONTROL) & EMAC_MACCONTROL_GMIIEN; HWREG(emacBase + EMAC_MACCONTROL) &= (~(uint32)EMAC_MACCONTROL_GMIIEN); /*Disable Loopback */ HWREG(emacBase + EMAC_MACCONTROL) &= (~(uint32)EMAC_MACCONTROL_LOOPBACK); /*Restore the value of GMIIEN bit */ HWREG(emacBase + EMAC_MACCONTROL) |= GMIIENval; } /** * \brief Enable Transmit Flow Control. * * \param emacBase Base Address of the EMAC module registers. * \return None * **/ /* SourceId : ETH_SourceId_040 */ /* DesignId : ETH_DesignId_040*/ /* Requirements : HL_ETH_SR20 */ void EMACTxFlowControlEnable(uint32 emacBase) { HWREG(emacBase + EMAC_MACCONTROL) |= EMAC_MACCONTROL_TXFLOWEN; } /** * \brief Disable Transmit Flow Control. * * \param emacBase Base Address of the EMAC module registers. * \return None * **/ /* SourceId : ETH_SourceId_041 */ /* DesignId : ETH_DesignId_041*/ /* Requirements : HL_ETH_SR20 */ void EMACTxFlowControlDisable(uint32 emacBase) { HWREG(emacBase + EMAC_MACCONTROL) &= (~(uint32)EMAC_MACCONTROL_TXFLOWEN); } /** * \brief Enable Receive Flow Control. * * \param emacBase Base Address of the EMAC module registers. * \return None * **/ /* SourceId : ETH_SourceId_042 */ /* DesignId : ETH_DesignId_042*/ /* Requirements : HL_ETH_SR20 */ void EMACRxFlowControlEnable(uint32 emacBase) { HWREG(emacBase + EMAC_MACCONTROL) |= EMAC_MACCONTROL_RXBUFFERFLOWEN; } /** * \brief Disable Receive Flow Control. * * \param emacBase Base Address of the EMAC module registers. * \return None * **/ /* SourceId : ETH_SourceId_043 */ /* DesignId : ETH_DesignId_043*/ /* Requirements : HL_ETH_SR20 */ void EMACRxFlowControlDisable(uint32 emacBase) { HWREG(emacBase + EMAC_MACCONTROL) &= (~(uint32)EMAC_MACCONTROL_RXBUFFERFLOWEN); } /** * \brief Receive flow threshold. These bits contain the threshold value for issuing flow control on incoming frames for channel n (when enabled). * * \param emacBase Base Address of the EMAC module registers. * \param channel Channel Number * \param threshold threshold value for issuing flow control on incoming frames for the given channel * \return None * **/ /* SourceId : ETH_SourceId_044 */ /* DesignId : ETH_DesignId_044*/ /* Requirements : HL_ETH_SR20 */ void EMACRxSetFlowThreshold(uint32 emacBase, uint32 channel, uint32 threshold) { HWREG(emacBase + EMAC_RXFLOWTHRESH(channel)) &= (0x0U); HWREG(emacBase + EMAC_RXFLOWTHRESH(channel)) |= threshold; } /** * \brief This function reads the contents of the 36 network statistics registers that are present in the module. * \param emacBase Base Address of the EMAC module registers. * \param statRegNo The number of the register with RXGOODFRAMES (Offset= 0x200) being 0. Refer the Technical Reference Manual for the list of registers and their contents. * \return uint32 **/ /* SourceId : ETH_SourceId_045 */ /* DesignId : ETH_DesignId_045*/ /* Requirements : HL_ETH_SR29 */ uint32 EMACReadNetStatRegisters(uint32 emacBase, uint32 statRegNo) { return HWREG(emacBase + EMAC_NETSTATREGS(statRegNo)); } /** * \brief Function to read values of Transmit Interrupt Status registers (TXINTSTATMASKED and TXINTSTATRAW) * * \param emacBase Base Address of the EMAC module registers. * \param channel Channel Number * \param txintstat pointer to the emac_tx_int_status Structure that will store the register values that have been read * \return None * **/ /* SourceId : ETH_SourceId_046 */ /* DesignId : ETH_DesignId_046*/ /* Requirements : HL_ETH_SR23 */ void EMACTxIntStat(uint32 emacBase, uint32 channel, emac_tx_int_status_t *txintstat) { txintstat->intstatmasked = (HWREG(emacBase + EMAC_TXINTSTATMASKED) & ((uint32)1U << channel)); txintstat->intstatraw = (HWREG(emacBase + EMAC_TXINTSTATRAW) & ((uint32)1U << channel)); } /** * \brief Function to read values of Receive Interrupt Status registers (RXINTSTATMASKED, RXINTSTATRAW) * * \param emacBase Base Address of the EMAC module registers. * \param channel Channel Number * \param rxintstat pointer to the emac_rx_int_status Structure that will store the register values that have been read. * \return None **/ /* SourceId : ETH_SourceId_047 */ /* DesignId : ETH_DesignId_047*/ /* Requirements : HL_ETH_SR23 */ void EMACRxIntStat(uint32 emacBase, uint32 channel, emac_rx_int_status_t *rxintstat) { rxintstat->intstatmasked_pend = (HWREG(emacBase + EMAC_RXINTSTATMASKED) & ((uint32)0x1U << (uint32)(channel))); rxintstat->intstatmasked_threshpend = (HWREG(emacBase + EMAC_RXINTSTATMASKED) & ((uint32)0x1U << ((uint32)0x8U + (uint32)(channel)))); rxintstat->intstatraw_pend = (HWREG(emacBase + EMAC_RXINTSTATRAW) & ((uint32)0x1U << (uint32)(channel))); rxintstat->intstatraw_threshpend = (HWREG(emacBase + EMAC_RXINTSTATRAW) & ((uint32)0x1U << ((uint32)0x8U + (uint32)(channel)))); } /** * \brief Tx and Rx Buffer Descriptors are initialized. Buffer pointers are allocated to the Rx Descriptors. * * \param hdkif network interface structure * \return None * **/ /* SourceId : ETH_SourceId_048 */ /* DesignId : ETH_DesignId_048*/ /* Requirements : HL_ETH_SR17,HL_ETH_SR30 */ void EMACDMAInit(hdkif_t *hdkif) { uint32 num_bd, pbuf_cnt = 0U; volatile emac_tx_bd_t *curr_txbd, *last_txbd; volatile emac_rx_bd_t *curr_bd, *last_bd; txch_t *txch_dma; rxch_t *rxch_dma; uint8_t *p; txch_dma = &(hdkif->txchptr); /** * Initialize the Descriptor Memory For TX and RX * Only single channel is supported for both TX and RX */ /*SAFETYMCUSW 134 S MR:12.2 "LDRA Tool issue" */ /*SAFETYMCUSW 45 D MR:21.1 "Valid non NULL input parameters are assigned in this driver" */ txch_dma->free_head = (volatile emac_tx_bd_t*)(hdkif->emac_ctrl_ram); txch_dma->next_bd_to_process = txch_dma->free_head; txch_dma->active_tail = NULL; /* Set the number of descriptors for the channel */ num_bd = (SIZE_EMAC_CTRL_RAM >> 1U) / sizeof(emac_tx_bd_t); /*SAFETYMCUSW 45 D MR:21.1 "Valid non NULL input parameters are assigned in this driver" */ curr_txbd = txch_dma->free_head; /*SAFETYMCUSW 45 D MR:21.1 "Valid non NULL input parameters are assigned in this driver" */ last_txbd = curr_txbd; /* Initialize all the TX buffer Descriptors */ while(num_bd != 0U) { /*SAFETYMCUSW 567 S MR:17.1,17.4 "Struct pointer used for linked list is incremented." */ curr_txbd->next = curr_txbd + 1U; /*SAFETYMCUSW 45 D MR:21.1 "Valid non NULL input parameters are assigned in this driver" */ curr_txbd->flags_pktlen = 0U; /*SAFETYMCUSW 45 D MR:21.1 "Valid non NULL input parameters are assigned in this driver" */ last_txbd = curr_txbd; /*SAFETYMCUSW 45 D MR:21.1 "Valid non NULL input parameters are assigned in this driver" */ curr_txbd = curr_txbd->next; num_bd--; } /*SAFETYMCUSW 134 S MR:12.2 "LDRA Tool issue" */ /*SAFETYMCUSW 45 D MR:21.1 "Valid non NULL input parameters are assigned in this driver" */ last_txbd->next = txch_dma->free_head; /* Initialize the descriptors for the RX channel */ /*SAFETYMCUSW 45 D MR:21.1 "Valid non NULL input parameters are assigned in this driver" */ rxch_dma = &(hdkif->rxchptr); /*SAFETYMCUSW 45 D MR:21.1 "Valid non NULL input parameters are assigned in this driver" */ /*SAFETYMCUSW 567 S MR:17.1,17.4 "Struct pointer used for linked list is incremented." */ curr_txbd++; /*SAFETYMCUSW 94 S MR:11.1,11.2,11.4 "Linked List pointer needs to be assigned." */ /*SAFETYMCUSW 95 S MR:11.1,11.4 "Linked List pointer needs to be assigned." */ /*SAFETYMCUSW 344 S MR:11.5 "Linked List pointer needs to be assigned to a different structure." */ /*SAFETYMCUSW 45 D MR:21.1 "Valid non NULL input parameters are assigned in this driver" */ rxch_dma->active_head = (volatile emac_rx_bd_t *)curr_txbd; /*SAFETYMCUSW 45 D MR:21.1 "Valid non NULL input parameters are assigned in this driver" */ rxch_dma->free_head = NULL; /*SAFETYMCUSW 45 D MR:21.1 "Valid non NULL input parameters are assigned in this driver" */ curr_bd = rxch_dma->active_head; /*SAFETYMCUSW 45 D MR:21.1 "Valid non NULL input parameters are assigned in this driver" */ last_bd = curr_bd; /* ** Static allocation of a specific number of packet buffers as specified by MAX_RX_PBUF_ALLOC, whose value is entered by the user in HALCoGen GUI. */ /*Commented part of allocation of pbufs need to check whether its true*/ for(pbuf_cnt = 0U;pbuf_cnt < MAX_RX_PBUF_ALLOC;pbuf_cnt++) { /*SAFETYMCUSW 45 D MR:21.1 "Valid non NULL input parameters are assigned in this driver" */ p = pbuf_array[pbuf_cnt]; /*SAFETYMCUSW 439 S MR:11.3 "RHS is a pointer value required to be stored. - Advisory as per MISRA" */ /*SAFETYMCUSW 45 D MR:21.1 "Valid non NULL input parameters are assigned in this driver" */ curr_bd->bufptr = (uint32)p; /*SAFETYMCUSW 45 D MR:21.1 "Valid non NULL input parameters are assigned in this driver" */ curr_bd->bufoff_len = MAX_TRANSFER_UNIT; /*SAFETYMCUSW 45 D MR:21.1 "Valid non NULL input parameters are assigned in this driver" */ curr_bd->flags_pktlen = EMAC_BUF_DESC_OWNER; if (pbuf_cnt == (MAX_RX_PBUF_ALLOC - 1U)) { /*SAFETYMCUSW 45 D MR:21.1 "Valid non NULL input parameters are assigned in this driver" */ curr_bd->next = NULL; /*SAFETYMCUSW 45 D MR:21.1 "Valid non NULL input parameters are assigned in this driver" */ last_bd = curr_bd; } else { /*SAFETYMCUSW 567 S MR:17.1,17.4 "Struct pointer used for linked list is incremented." */ curr_bd->next = (curr_bd + 1U); /*SAFETYMCUSW 567 S MR:17.1,17.4 "Struct pointer used for linked list is incremented." */ curr_bd++; /*SAFETYMCUSW 45 D MR:21.1 "Valid non NULL input parameters are assigned in this driver" */ last_bd = curr_bd; } } /*SAFETYMCUSW 134 S MR:12.2 "LDRA Tool issue" */ /*SAFETYMCUSW 45 D MR:21.1 "Valid non NULL input parameters are assigned in this driver" */ last_bd->next = NULL; /*SAFETYMCUSW 45 D MR:21.1 "Valid non NULL input parameters are assigned in this driver" */ rxch_dma->active_tail = last_bd; } /** * \brief Initializes the EMAC module for transmission and reception. * * \param macaddr MAC Address of the Module. * \param channel Channel Number. * * \return EMAC_ERR_OK if everything gets initialized * EMAC_ERR_CONN in case of an error in connecting. * **/ /* SourceId : ETH_SourceId_049 */ /* DesignId : ETH_DesignId_049*/ /* Requirements : HL_ETH_SR6 */ uint32 EMACHWInit(uint8_t macaddr[6U]) { uint32 temp, channel; volatile uint32 phyID=0U; volatile uint32 delay = 0xFFFU; uint32 phyIdReadCount = 0xFFFFU; volatile uint32 phyLinkRetries = 0xFFFFU; hdkif_t *hdkif; rxch_t *rxch; uint32 retVal = EMAC_ERR_OK; uint32 emacBase = 0U; #if(EMAC_MII_ENABLE == 0U) uint16 partnr_spd; #endif hdkif = &hdkif_data[0U]; EMACInstConfig(hdkif); /* set MAC hardware address */ for(temp = 0U; temp < EMAC_HWADDR_LEN; temp++) { hdkif->mac_addr[temp] = macaddr[(EMAC_HWADDR_LEN - 1U) - temp]; } /*Initialize the EMAC, EMAC Control and MDIO modules. */ EMACInit(hdkif->emac_ctrl_base, hdkif->emac_base); MDIOInit(hdkif->mdio_base, MDIO_FREQ_INPUT, MDIO_FREQ_OUTPUT); /*SAFETYMCUSW 134 S MR:12.2 "LDRA Tool issue" */ while(delay != 0U) { /*SAFETYMCUSW 134 S MR:12.2 "LDRA Tool issue" */ delay--; } /* Set the MAC Addresses in EMAC hardware */ emacBase = hdkif->emac_base; /* MISRA Code Fix (12.2) */ EMACMACSrcAddrSet(emacBase, hdkif->mac_addr); for(channel = 0U; channel < 8U; channel++) { emacBase = hdkif->emac_base; EMACMACAddrSet(emacBase, channel, hdkif->mac_addr, EMAC_MACADDR_MATCH); } /*SAFETYMCUSW 134 S MR:12.2 "LDRA Tool issue" */ while ((phyID == 0U) && (phyIdReadCount > 0U)) { phyID = Dp83640IDGet(hdkif->mdio_base,hdkif->phy_addr); phyIdReadCount--; } if (0U == phyID) { retVal = EMAC_ERR_CONNECT; } else { } if((uint32)0U == ((MDIOPhyAliveStatusGet(hdkif->mdio_base) >> hdkif->phy_addr) & (uint32)0x01U )) { retVal = EMAC_ERR_CONNECT; } else { } #if(EMAC_MII_ENABLE == 0U) Dp83640PartnerSpdGet(hdkif->mdio_base, hdkif->phy_addr, &partnr_spd); if((partnr_spd & 2U)==0U) { EMACRMIISpeedSet(hdkif->emac_base, EMAC_MACCONTROL_RMIISPEED); } #endif if(!Dp83640LinkStatusGet(hdkif->mdio_base, (uint32)EMAC_PHYADDRESS, (uint32)phyLinkRetries)) { retVal = EMAC_ERR_CONNECT; } else { } if(EMACLinkSetup(hdkif) != EMAC_ERR_OK) { retVal = EMAC_ERR_CONNECT; } else { } /* The transmit and receive buffer descriptors are initialized here. * Also, packet buffers are allocated to the receive buffer descriptors. */ EMACDMAInit(hdkif); /* Acknowledge receive and transmit interrupts for proper interrupt pulsing*/ EMACCoreIntAck(hdkif->emac_base, (uint32)EMAC_INT_CORE0_RX); EMACCoreIntAck(hdkif->emac_base, (uint32)EMAC_INT_CORE0_TX); /* Enable GMII bit in the MACCONTROL Rgister*/ /*SAFETYMCUSW 139 S MR:13.7 "Parameter is taken as input from GUI." */ EMACMIIEnable(hdkif->emac_base); /* Enable Broadcast if enabled in the GUI. */ /*SAFETYMCUSW 139 S MR:13.7 "Parameter is taken as input from GUI." */ #if(EMAC_BROADCAST_ENABLE) EMACRxBroadCastEnable(hdkif->emac_base, (uint32)EMAC_CHANNELNUMBER); #else /*SAFETYMCUSW 1 J MR:14.1 "If condition parameter is taken as input from GUI." */ /*SAFETYMCUSW 1 J MR:14.1 "If condition parameter is taken as input from GUI." */ EMACRxBroadCastDisable(hdkif->emac_base, (uint32)EMAC_CHANNELNUMBER); #endif /* Enable Broadcast if enabled in the GUI. */ /*SAFETYMCUSW 139 S MR:13.7 "Parameter is taken as input from GUI." */ #if(EMAC_UNICAST_ENABLE) EMACRxUnicastSet(hdkif->emac_base, (uint32)EMAC_CHANNELNUMBER); #else /*SAFETYMCUSW 1 J MR:14.1 "If condition parameter is taken as input from GUI." */ EMACRxUnicastClear(hdkif->emac_base, (uint32)EMAC_CHANNELNUMBER); #endif /*Enable Full Duplex or Half-Duplex mode based on GUI Input. */ /*SAFETYMCUSW 139 S MR:13.7 "Parameter is taken as input from GUI." */ #if (EMAC_FULL_DUPLEX_ENABLE) EMACDuplexSet(EMAC_0_BASE, (uint32)EMAC_DUPLEX_FULL); #else /*SAFETYMCUSW 1 J MR:14.1 "If condition arameter is taken as input from GUI." */ EMACDuplexSet(EMAC_0_BASE, (uint32)EMAC_DUPLEX_HALF); #endif /* Enable Loopback based on GUI Input */ /*SAFETYMCUSW 139 S MR:13.7 "Parameter is taken as input from GUI." */ #if(EMAC_LOOPBACK_ENABLE) EMACEnableLoopback(hdkif->emac_base); #else /*SAFETYMCUSW 1 J MR:14.1 "If condition parameter is taken as input from GUI." */ EMACDisableLoopback(hdkif->emac_base); #endif /* Enable Transmit and Transmit Interrupt */ /*SAFETYMCUSW 139 S MR:13.7 "Parameter is taken as input from GUI." */ #if(EMAC_TX_ENABLE) EMACTxEnable(hdkif->emac_base); EMACTxIntPulseEnable(hdkif->emac_base, hdkif->emac_ctrl_base, (uint32)EMAC_CHANNELNUMBER, (uint32)EMAC_CHANNELNUMBER); #else /*SAFETYMCUSW 1 J MR:14.1 "If condition parameter is taken as input from GUI." */ /*SAFETYMCUSW 1 J MR:14.1 "If condition parameter is taken as input from GUI." */ EMACTxDisable(hdkif->emac_base); EMACTxIntPulseDisable(hdkif->emac_base, hdkif->emac_ctrl_base, (uint32)EMAC_CHANNELNUMBER, (uint32)EMAC_CHANNELNUMBER); #endif /* Enable Receive and Receive Interrupt. Then start receiving by writing to the HDP register. */ /*SAFETYMCUSW 139 S MR:13.7 "Parameter is taken as input from GUI." */ #if(EMAC_RX_ENABLE) EMACNumFreeBufSet(hdkif->emac_base,(uint32)EMAC_CHANNELNUMBER , (uint32)MAX_RX_PBUF_ALLOC); EMACRxEnable(hdkif->emac_base); EMACRxIntPulseEnable(hdkif->emac_base, hdkif->emac_ctrl_base, (uint32)EMAC_CHANNELNUMBER, (uint32)EMAC_CHANNELNUMBER); rxch = &(hdkif->rxchptr); /* Write to the RX HDP for channel 0 */ /*SAFETYMCUSW 45 D MR:21.1 "Valid non NULL input parameters are assigned in this driver" */ EMACRxHdrDescPtrWrite(hdkif->emac_base, (uint32)rxch->active_head, (uint32)EMAC_CHANNELNUMBER); #else /*SAFETYMCUSW 1 J MR:14.1 "If condition parameter is taken as input from GUI." */ /*SAFETYMCUSW 1 J MR:14.1 "If condition parameter is taken as input from GUI." */ EMACRxDisable(hdkif->emac_base); EMACRxIntPulseDisable(hdkif->emac_base, hdkif->emac_ctrl_base, (uint32)EMAC_CHANNELNUMBER, (uint32)EMAC_CHANNELNUMBER); #endif return retVal; } /** * This function should do the actual transmission of the packet. The packet is * contained in the pbuf that is passed to the function. This pbuf might be * chained. That is, one pbuf can span more than one tx buffer descriptors * * @param hdkif network interface structure * @param pbuf the pbuf structure which contains the data to be sent using EMAC * @return boolean. * -Returns FALSE if a Null pointer was passed for transmission * -Returns TRUE if valid data is sent and is transmitted. */ /* SourceId : ETH_SourceId_050 */ /* DesignId : ETH_DesignId_050*/ /* Requirements : HL_ETH_SR31 */ boolean EMACTransmit(hdkif_t *hdkif, pbuf_t *pbuf) { txch_t *txch; pbuf_t *q; uint16 totLen; uint16 qLen; volatile emac_tx_bd_t *curr_bd,*active_head, *bd_end; boolean retValue = FALSE; if((pbuf != NULL) && (hdkif != NULL)) { txch = &(hdkif->txchptr); /* Get the buffer descriptor which is free to transmit */ /*SAFETYMCUSW 45 D MR:21.1 "Valid non NULL input parameters are assigned in this driver" */ curr_bd = txch->free_head; /*SAFETYMCUSW 45 D MR:21.1 "Valid non NULL input parameters are assigned in this driver" */ bd_end = curr_bd; /*SAFETYMCUSW 45 D MR:21.1 "Valid non NULL input parameters are assigned in this driver" */ active_head = curr_bd; /* Update the total packet length */ /*SAFETYMCUSW 45 D MR:21.1 "Valid non NULL input parameters are assigned in this driver" */ curr_bd->flags_pktlen &= (~((uint32)0xFFFFU)); /*SAFETYMCUSW 45 D MR:21.1 "Valid non NULL input parameters are assigned in this driver" */ totLen = pbuf->tot_len; curr_bd->flags_pktlen |= (uint32)(totLen); /* Indicate the start of the packet */ /*SAFETYMCUSW 45 D MR:21.1 "Valid non NULL input parameters are assigned in this driver" */ curr_bd->flags_pktlen |= (EMAC_BUF_DESC_SOP | EMAC_BUF_DESC_OWNER); /* Copy pbuf information into TX buffer descriptors */ q = pbuf; while(q != NULL) { /* Initialize the buffer pointer and length */ /*SAFETYMCUSW 439 S MR:11.3 "RHS is a pointer value required to be stored. - Advisory as per MISRA" */ /*SAFETYMCUSW 45 D MR:21.1 "Valid non NULL input parameters are assigned in this driver" */ curr_bd->bufptr = (uint32)(q->payload); /*SAFETYMCUSW 45 D MR:21.1 "Valid non NULL input parameters are assigned in this driver" */ qLen = q->len; curr_bd->bufoff_len = ((uint32)(qLen) & 0xFFFFU); /*SAFETYMCUSW 45 D MR:21.1 "Valid non NULL input parameters are assigned in this driver" */ bd_end = curr_bd; /*SAFETYMCUSW 45 D MR:21.1 "Valid non NULL input parameters are assigned in this driver" */ curr_bd = curr_bd->next; q = q->next; } /* Indicate the start and end of the packet */ /*SAFETYMCUSW 134 S MR:12.2 "LDRA Tool issue" */ /*SAFETYMCUSW 45 D MR:21.1 "Valid non NULL input parameters are assigned in this driver" */ bd_end->next = NULL; /*SAFETYMCUSW 134 S MR:12.2 "LDRA Tool issue" */ bd_end->flags_pktlen |= EMAC_BUF_DESC_EOP; /*SAFETYMCUSW 71 S MR:17.6 "Assigned pointer value has required scope." */ txch->free_head = curr_bd; /* For the first time, write the HDP with the filled bd */ if(txch->active_tail == NULL) { /*SAFETYMCUSW 439 S MR:11.3 "Address stored in pointer is passed as as an int parameter. - Advisory as per MISRA" */ /*SAFETYMCUSW 45 D MR:21.1 "Valid non NULL input parameters are assigned in this driver" */ EMACTxHdrDescPtrWrite(hdkif->emac_base, (uint32)(active_head), (uint32)EMAC_CHANNELNUMBER); } /* * Chain the bd's. If the DMA engine, already reached the end of the chain, * the EOQ will be set. In that case, the HDP shall be written again. */ else { /*SAFETYMCUSW 45 D MR:21.1 "Valid non NULL input parameters are assigned in this driver" */ curr_bd = txch->active_tail; /* Wait for the EOQ bit is set */ /*SAFETYMCUSW 28 D MR:NA "Hardware status bit read check" */ /*SAFETYMCUSW 134 S MR:12.2 "LDRA Tool issue" */ /*SAFETYMCUSW 45 D MR:21.1 "Valid non NULL input parameters are assigned in this driver" */ while (EMAC_BUF_DESC_EOQ != (curr_bd->flags_pktlen & EMAC_BUF_DESC_EOQ)) { } /* Don't write to TXHDP0 until it turns to zero */ /*SAFETYMCUSW 28 D MR:NA "Hardware status bit read check" */ /*SAFETYMCUSW 134 S MR:12.2 "LDRA Tool issue" */ while (((uint32)0U != *((uint32 *)0xFCF78600U))) { } /*SAFETYMCUSW 45 D MR:21.1 "Valid non NULL input parameters are assigned in this driver" */ curr_bd->next = active_head; /*SAFETYMCUSW 134 S MR:12.2 "LDRA Tool issue" */ /*SAFETYMCUSW 45 D MR:21.1 "Valid non NULL input parameters are assigned in this driver" */ if (EMAC_BUF_DESC_EOQ == (curr_bd->flags_pktlen & EMAC_BUF_DESC_EOQ)) { /* Write the Header Descriptor Pointer and start DMA */ /*SAFETYMCUSW 439 S MR:11.3 "Address stored in pointer is passed as as an int parameter. - Advisory as per MISRA" */ /*SAFETYMCUSW 45 D MR:21.1 "Valid non NULL input parameters are assigned in this driver" */ EMACTxHdrDescPtrWrite(hdkif->emac_base, (uint32)(active_head), (uint32)EMAC_CHANNELNUMBER); } } /*SAFETYMCUSW 45 D MR:21.1 "Valid non NULL input parameters are assigned in this driver" */ txch->active_tail = bd_end; retValue = TRUE; } else { retValue = FALSE; } return retValue; } /** * Function for processing Tx buffer descriptors. * * @param hdkif interface structure * @return none */ /* SourceId : ETH_SourceId_051 */ /* DesignId : ETH_DesignId_051*/ /* Requirements : HL_ETH_SR15 */ void EMACTxIntHandler(hdkif_t *hdkif) { txch_t *txch_int; volatile emac_tx_bd_t *curr_bd, *next_bd_to_process; txch_int = &(hdkif->txchptr); /*SAFETYMCUSW 45 D MR:21.1 "Valid non NULL input parameters are assigned in this driver" */ next_bd_to_process = txch_int->next_bd_to_process; /*SAFETYMCUSW 45 D MR:21.1 "Valid non NULL input parameters are assigned in this driver" */ curr_bd = next_bd_to_process; /* Check for correct start of packet */ /*SAFETYMCUSW 134 S MR:12.2 "LDRA Tool issue" */ /*SAFETYMCUSW 45 D MR:21.1 "Valid non NULL input parameters are assigned in this driver" */ while(((curr_bd->flags_pktlen) & EMAC_BUF_DESC_SOP) == EMAC_BUF_DESC_SOP) { /* Make sure that the transmission is over */ /*SAFETYMCUSW 28 D MR:NA "Hardware status bit read check" */ /*SAFETYMCUSW 134 S MR:12.2 "LDRA Tool issue" */ /*SAFETYMCUSW 45 D MR:21.1 "Valid non NULL input parameters are assigned in this driver" */ while(((curr_bd->flags_pktlen) & EMAC_BUF_DESC_OWNER) == EMAC_BUF_DESC_OWNER) { } /* Traverse till the end of packet is reached */ /*SAFETYMCUSW 134 S MR:12.2 "LDRA Tool issue" */ /*SAFETYMCUSW 45 D MR:21.1 "Valid non NULL input parameters are assigned in this driver" */ while(((curr_bd->flags_pktlen) & EMAC_BUF_DESC_EOP) != EMAC_BUF_DESC_EOP) { curr_bd = curr_bd->next; } /*SAFETYMCUSW 134 S MR:12.2 "LDRA Tool issue" */ /*SAFETYMCUSW 45 D MR:21.1 "Valid non NULL input parameters are assigned in this driver" */ next_bd_to_process->flags_pktlen &= ~(EMAC_BUF_DESC_SOP); /*SAFETYMCUSW 45 D MR:21.1 "Valid non NULL input parameters are assigned in this driver" */ curr_bd->flags_pktlen &= ~(EMAC_BUF_DESC_EOP); /** * If there are no more data transmitted, the next interrupt * shall happen with the pbuf associated with the free_head */ /*SAFETYMCUSW 45 D MR:21.1 "Valid non NULL input parameters are assigned in this driver" */ if(curr_bd->next == NULL) { /*SAFETYMCUSW 45 D MR:21.1 "Valid non NULL input parameters are assigned in this driver" */ txch_int->next_bd_to_process = txch_int->free_head; } else { /*SAFETYMCUSW 45 D MR:21.1 "Valid non NULL input parameters are assigned in this driver" */ txch_int->next_bd_to_process = curr_bd->next; } /* Acknowledge the EMAC and free the corresponding pbuf */ /*SAFETYMCUSW 439 S MR:11.3 "Address stored in pointer is passed as as an int parameter. - Advisory as per MISRA" */ /*SAFETYMCUSW 45 D MR:21.1 "Valid non NULL input parameters are assigned in this driver" */ /*SAFETYMCUSW 344 S MR:11.5 "Address stored in pointer is passed as as an int parameter." */ EMACTxCPWrite(hdkif->emac_base, (uint32)EMAC_CHANNELNUMBER, (uint32)curr_bd); /*SAFETYMCUSW 45 D MR:21.1 "Valid non NULL input parameters are assigned in this driver" */ next_bd_to_process = txch_int->next_bd_to_process; /*SAFETYMCUSW 45 D MR:21.1 "Valid non NULL input parameters are assigned in this driver" */ curr_bd = next_bd_to_process; } } /** * Function for processing received packets. * * @param hdkif interface structure * @return none */ /* SourceId : ETH_SourceId_052 */ /* DesignId : ETH_DesignId_052*/ /* Requirements : HL_ETH_SR31 */ void EMACReceive(hdkif_t *hdkif) { rxch_t *rxch_int; volatile emac_rx_bd_t *curr_bd, *curr_tail, *last_bd; /* The receive structure that holds data about a particular receive channel */ rxch_int = &(hdkif->rxchptr); /* Get the buffer descriptors which contain the earliest filled data */ /*SAFETYMCUSW 45 D MR:21.1 "Valid non NULL input parameters are assigned in this driver" */ curr_bd = rxch_int->active_head; /*SAFETYMCUSW 45 D MR:21.1 "Valid non NULL input parameters are assigned in this driver" */ last_bd = rxch_int->active_tail; /** * Process the descriptors as long as data is available * when the DMA is receiving data, SOP flag will be set */ /*SAFETYMCUSW 28 D MR:NA "Hardware status bit read check" */ /*SAFETYMCUSW 134 S MR:12.2 "LDRA Tool issue" */ /*SAFETYMCUSW 45 D MR:21.1 "Valid non NULL input parameters are assigned in this driver" */ while((curr_bd->flags_pktlen & EMAC_BUF_DESC_SOP) == EMAC_BUF_DESC_SOP) { /* Start processing once the packet is loaded */ /*SAFETYMCUSW 134 S MR:12.2 "LDRA Tool issue" */ /*SAFETYMCUSW 45 D MR:21.1 "Valid non NULL input parameters are assigned in this driver" */ if((curr_bd->flags_pktlen & EMAC_BUF_DESC_OWNER) != EMAC_BUF_DESC_OWNER) { /* this bd chain will be freed after processing */ /*SAFETYMCUSW 71 S MR:17.6 "Assigned pointer value has required scope." */ /*SAFETYMCUSW 45 D MR:21.1 "Valid non NULL input parameters are assigned in this driver" */ rxch_int->free_head = curr_bd; /* Get the total length of the packet. curr_bd points to the start * of the packet. */ /* * The loop runs till it reaches the end of the packet. */ /*SAFETYMCUSW 134 S MR:12.2 "LDRA Tool issue" */ /*SAFETYMCUSW 45 D MR:21.1 "Valid non NULL input parameters are assigned in this driver" */ while((curr_bd->flags_pktlen & EMAC_BUF_DESC_EOP)!= EMAC_BUF_DESC_EOP) { /*Update the flags for the descriptor again and the length of the buffer*/ /*SAFETYMCUSW 45 D MR:21.1 "Valid non NULL input parameters are assigned in this driver" */ curr_bd->flags_pktlen = (uint32)EMAC_BUF_DESC_OWNER; /*SAFETYMCUSW 45 D MR:21.1 "Valid non NULL input parameters are assigned in this driver" */ curr_bd->bufoff_len = (uint32)MAX_TRANSFER_UNIT; /*SAFETYMCUSW 45 D MR:21.1 "Valid non NULL input parameters are assigned in this driver" */ last_bd = curr_bd; /*SAFETYMCUSW 45 D MR:21.1 "Valid non NULL input parameters are assigned in this driver" */ curr_bd = curr_bd->next; } /* Updating the last descriptor (which contained the EOP flag) */ /*SAFETYMCUSW 45 D MR:21.1 "Valid non NULL input parameters are assigned in this driver" */ curr_bd->flags_pktlen = (uint32)EMAC_BUF_DESC_OWNER; /*SAFETYMCUSW 45 D MR:21.1 "Valid non NULL input parameters are assigned in this driver" */ curr_bd->bufoff_len = (uint32)MAX_TRANSFER_UNIT; /*SAFETYMCUSW 45 D MR:21.1 "Valid non NULL input parameters are assigned in this driver" */ last_bd = curr_bd; /*SAFETYMCUSW 45 D MR:21.1 "Valid non NULL input parameters are assigned in this driver" */ curr_bd = curr_bd->next; /* Acknowledge that this packet is processed */ /*SAFETYMCUSW 439 S MR:11.3 "Address stored in pointer is passed as as an int parameter. - Advisory as per MISRA" */ /*SAFETYMCUSW 45 D MR:21.1 "Valid non NULL input parameters are assigned in this driver" */ EMACRxCPWrite(hdkif->emac_base, (uint32)EMAC_CHANNELNUMBER, (uint32)last_bd); /* The next buffer descriptor is the new head of the linked list. */ /*SAFETYMCUSW 71 S MR:17.6 "Assigned pointer value has required scope." */ /*SAFETYMCUSW 45 D MR:21.1 "Valid non NULL input parameters are assigned in this driver" */ rxch_int->active_head = curr_bd; /* The processed descriptor is now the tail of the linked list. */ /*SAFETYMCUSW 45 D MR:21.1 "Valid non NULL input parameters are assigned in this driver" */ curr_tail = rxch_int->active_tail; /*SAFETYMCUSW 134 S MR:12.2 "LDRA Tool issue" */ /*SAFETYMCUSW 45 D MR:21.1 "Valid non NULL input parameters are assigned in this driver" */ curr_tail->next = rxch_int->free_head; /* The last element in the already processed Rx descriptor chain is now the end of list. */ /*SAFETYMCUSW 134 S MR:12.2 "LDRA Tool issue" */ /*SAFETYMCUSW 45 D MR:21.1 "Valid non NULL input parameters are assigned in this driver" */ last_bd->next = NULL; /** * Check if the reception has ended. If the EOQ flag is set, the NULL * Pointer is taken by the DMA engine. So we need to write the RX HDP * with the next descriptor. */ /*SAFETYMCUSW 134 S MR:12.2 "LDRA Tool issue" */ /*SAFETYMCUSW 134 S MR:12.2 "LDRA Tool issue" */ /*SAFETYMCUSW 45 D MR:21.1 "Valid non NULL input parameters are assigned in this driver" */ if((curr_tail->flags_pktlen & EMAC_BUF_DESC_EOQ) == EMAC_BUF_DESC_EOQ) { /*SAFETYMCUSW 439 S MR:11.3 "Address stored in pointer is passed as as an int parameter. - Advisory as per MISRA" */ /*SAFETYMCUSW 45 D MR:21.1 "Valid non NULL input parameters are assigned in this driver" */ EMACRxHdrDescPtrWrite(hdkif->emac_base, (uint32)(rxch_int->free_head), (uint32)EMAC_CHANNELNUMBER); } /*SAFETYMCUSW 71 S MR:17.6 "Assigned pointer value has required scope." */ /*SAFETYMCUSW 45 D MR:21.1 "Valid non NULL input parameters are assigned in this driver" */ /*SAFETYMCUSW 45 D MR:21.1 "Valid non NULL input parameters are assigned in this driver" */ rxch_int->free_head = curr_bd; rxch_int->active_tail = last_bd; } } } /** @fn void EMACGetConfigValue(emac_config_reg_t *config_reg, config_value_type_t type) * @brief Get the initial or current values of the configuration registers * * @param[in] *config_reg: pointer to the struct to which the initial or current * value of the configuration registers need to be stored * @param[in] type: whether initial or current value of the configuration registers need to be stored * - InitialValue: initial value of the configuration registers will be stored * in the struct pointed by config_reg * - CurrentValue: initial value of the configuration registers will be stored * in the struct pointed by config_reg * * This function will copy the initial or current value (depending on the parameter 'type') * of the configuration registers to the struct pointed by config_reg * */ /* SourceId : ETH_SourceId_053 */ /* DesignId : ETH_DesignId_053*/ /* Requirements : HL_ETH_SR52 */ void EMACGetConfigValue(emac_config_reg_t *config_reg, config_value_type_t type) { if (type == InitialValue) { config_reg->TXCONTROL = EMAC_TXCONTROL_CONFIGVALUE; config_reg->RXCONTROL = EMAC_RXCONTROL_CONFIGVALUE; config_reg->TXINTMASKSET = EMAC_TXINTMASKSET_CONFIGVALUE; config_reg->TXINTMASKCLEAR = EMAC_TXINTMASKCLEAR_CONFIGVALUE; config_reg->RXINTMASKSET = EMAC_RXINTMASKSET_CONFIGVALUE; config_reg->RXINTMASKCLEAR = EMAC_RXINTMASKCLEAR_CONFIGVALUE; config_reg->MACSRCADDRHI = EMAC_MACSRCADDRHI_CONFIGVALUE; config_reg->MACSRCADDRLO = EMAC_MACSRCADDRLO_CONFIGVALUE; config_reg->MDIOCONTROL = EMAC_MDIOCONTROL_CONFIGVALUE; config_reg->C0RXEN = EMAC_C0RXEN_CONFIGVALUE; config_reg->C0TXEN = EMAC_C0TXEN_CONFIGVALUE; } else { config_reg->TXCONTROL = HWREG(EMAC_0_BASE + EMAC_TXCONTROL); config_reg->RXCONTROL = HWREG(EMAC_0_BASE + EMAC_RXCONTROL); config_reg->TXINTMASKSET = HWREG(EMAC_0_BASE + EMAC_TXINTMASKSET); config_reg->TXINTMASKCLEAR = HWREG(EMAC_0_BASE + EMAC_TXINTMASKCLEAR); config_reg->RXINTMASKSET = HWREG(EMAC_0_BASE + EMAC_RXINTMASKSET); config_reg->RXINTMASKCLEAR = HWREG(EMAC_0_BASE + EMAC_RXINTMASKCLEAR); config_reg->MACSRCADDRHI = HWREG(EMAC_0_BASE + EMAC_MACSRCADDRHI); config_reg->MACSRCADDRLO = HWREG(EMAC_0_BASE + EMAC_MACSRCADDRLO); config_reg->MDIOCONTROL = HWREG(MDIO_0_BASE + MDIO_CONTROL); config_reg->C0RXEN = HWREG(EMAC_CTRL_0_BASE + EMAC_CTRL_CnRXEN(0U)); config_reg->C0TXEN = HWREG(EMAC_CTRL_0_BASE + EMAC_CTRL_CnTXEN(0U)); } } /* USER CODE BEGIN (2) */ /* USER CODE END */ /***************************** End Of File ***********************************/