Added K64F TCP/IP support

Currently NET_7 (HttpClient test) and NET_8 (NTP test) fail for
unknown reasons.
pull/274/head
Bogdan Marinescu 2014-04-23 16:11:07 +01:00 committed by bcostm
parent bbfdef0fac
commit 9a5f81d75c
40 changed files with 5296 additions and 175 deletions

View File

@ -0,0 +1,264 @@
/*
* Copyright (c) 2013 - 2014, Freescale Semiconductor, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o 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.
*
* o Neither the name of Freescale Semiconductor, Inc. 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 HOLDER 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.
*/
#include "fsl_phy_driver.h"
/*******************************************************************************
* Variables
******************************************************************************/
/*! @brief Define Phy API structure for MAC application*/
const enet_phy_api_t g_enetPhyApi =
{
phy_auto_discover,
phy_init,
phy_get_link_speed,
phy_get_link_status,
phy_get_link_duplex,
};
/*******************************************************************************
* Code
******************************************************************************/
/*FUNCTION****************************************************************
*
* Function Name: phy_init
* Return Value: The execution status.
* Description: Initialize Phy.
* This interface provides initialize functions for Phy, This is called by enet
* initialize function. Phy is usually deault auto-negotiation. so there is no
* need to do the intialize about this. we just need to check the loop mode.
*END*********************************************************************/
uint32_t phy_init(enet_dev_if_t * enetIfPtr)
{
uint32_t data;
uint32_t counter;
uint32_t result;
/* Check input parameters*/
if (!enetIfPtr)
{
return kStatus_PHY_InvaildInput;
}
/* Reset Phy*/
if ((result = (enetIfPtr->macApiPtr->enet_mii_read(enetIfPtr->deviceNumber,
enetIfPtr->phyCfgPtr->phyAddr,kEnetPhySR,&data))) == kStatus_PHY_Success)
{
if ((data & kEnetPhyAutoNegAble) != 0)
{
/* Set Autonegotiation*/
enetIfPtr->macApiPtr->enet_mii_write(enetIfPtr->deviceNumber,
enetIfPtr->phyCfgPtr->phyAddr, kEnetPhyCR, kEnetPhyAutoNeg);
for (counter = 0; counter < kPhyTimeout; counter++)
{
if (enetIfPtr->macApiPtr->enet_mii_read(enetIfPtr->deviceNumber,
enetIfPtr->phyCfgPtr->phyAddr,kEnetPhySR,&data)== kStatus_PHY_Success)
{
if ((data & kEnetPhyAutoNegComplete) != 0)
{
break;
}
}
}
if (counter == kPhyTimeout)
{
return kStatus_PHY_TimeOut;
}
}
}
if (enetIfPtr->phyCfgPtr->isLoopEnabled)
{
/* First read the current status in control register*/
if (enetIfPtr->macApiPtr->enet_mii_read(enetIfPtr->deviceNumber,
enetIfPtr->phyCfgPtr->phyAddr,kEnetPhyCR,&data))
{
result = enetIfPtr->macApiPtr->enet_mii_write(enetIfPtr->deviceNumber,
enetIfPtr->phyCfgPtr->phyAddr,kEnetPhyCR,(data|kEnetPhyLoop));
}
}
return result;
}
/*FUNCTION****************************************************************
*
* Function Name: phy_auto_discover
* Return Value: The execution status.
* Description: Phy address auto discover.
* This function provides a interface to get phy address using phy address auto
* discovering, this interface is used when the phy address is unknown.
*END*********************************************************************/
uint32_t phy_auto_discover(enet_dev_if_t * enetIfPtr)
{
uint32_t addrIdx,data;
uint32_t result = kStatus_PHY_Fail;
/* Check input parameters*/
if (!enetIfPtr)
{
return kStatus_PHY_InvaildInput;
}
for (addrIdx = 0; addrIdx < 32; addrIdx++)
{
enetIfPtr->phyCfgPtr->phyAddr = addrIdx;
result = enetIfPtr->macApiPtr->enet_mii_read(enetIfPtr->deviceNumber,
enetIfPtr->phyCfgPtr->phyAddr,kEnetPhyId1,&data);
if ((result == kStatus_PHY_Success) && (data != 0) && (data != 0xffff) )
{
return kStatus_PHY_Success;
}
}
return result;
}
/*FUNCTION****************************************************************
*
* Function Name: phy_get_link_speed
* Return Value: The execution status.
* Description: Get phy link speed.
* This function provides a interface to get link speed.
*END*********************************************************************/
uint32_t phy_get_link_speed(enet_dev_if_t * enetIfPtr, enet_phy_speed_t *status)
{
uint32_t result = kStatus_PHY_Success;
uint32_t data;
/* Check input parameters*/
if ((!enetIfPtr) || (!status))
{
return kStatus_PHY_InvaildInput;
}
result = enetIfPtr->macApiPtr->enet_mii_read(enetIfPtr->deviceNumber,
enetIfPtr->phyCfgPtr->phyAddr, kEnetPhyCt2,&data);
if (result == kStatus_PHY_Success)
{
data &= kEnetPhySpeedDulpexMask;
if ((kEnetPhy100HalfDuplex == data) || (kEnetPhy100FullDuplex == data))
{
*status = kEnetSpeed100M;
}
else
{
*status = kEnetSpeed10M;
}
}
return result;
}
/*FUNCTION****************************************************************
*
* Function Name: phy_get_link_status
* Return Value: The execution status.
* Description: Get phy link status.
* This function provides a interface to get link status to see if the link
* status is on or off.
*END*********************************************************************/
uint32_t phy_get_link_status(enet_dev_if_t * enetIfPtr, bool *status)
{
uint32_t result = kStatus_PHY_Success;
uint32_t data;
/* Check input parameters*/
if ((!enetIfPtr) || (!status))
{
return kStatus_PHY_InvaildInput;
}
result = enetIfPtr->macApiPtr->enet_mii_read(enetIfPtr->deviceNumber,
enetIfPtr->phyCfgPtr->phyAddr,kEnetPhyCR,&data);
if ((result == kStatus_PHY_Success) && (!(data & kEnetPhyReset)))
{
data = 0;
result = enetIfPtr->macApiPtr->enet_mii_read(enetIfPtr->deviceNumber,
enetIfPtr->phyCfgPtr->phyAddr,kEnetPhySR, &data);
if (result == kStatus_PHY_Success)
{
if (!(kEnetPhyLinkStatus & data))
{
*status = false;
}
else
{
*status = true;
}
}
}
return result;
}
/*FUNCTION****************************************************************
*
* Function Name: phy_get_link_duplex
* Return Value: The execution status.
* Description: Get phy link duplex.
* This function provides a interface to get link duplex to see if the link
* duplex is full or half.
*END*********************************************************************/
uint32_t phy_get_link_duplex(enet_dev_if_t * enetIfPtr, enet_phy_duplex_t *status)
{
uint32_t result = kStatus_PHY_Success;
uint32_t data;
/* Check input parameters*/
if ((!enetIfPtr) || (!status))
{
return kStatus_PHY_InvaildInput;
}
result = enetIfPtr->macApiPtr->enet_mii_read(enetIfPtr->deviceNumber,
enetIfPtr->phyCfgPtr->phyAddr,kEnetPhyCt2,&data);
if (result == kStatus_PHY_Success)
{
data &= kEnetPhySpeedDulpexMask;
if ((kEnetPhy10FullDuplex == data) || (kEnetPhy100FullDuplex == data))
{
*status = kEnetFullDuplex;
}
else
{
*status = kEnetHalfDuplex;
}
}
return result;
}
/*******************************************************************************
* EOF
******************************************************************************/

View File

@ -0,0 +1,190 @@
/*
* Copyright (c) 2013 - 2014, Freescale Semiconductor, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o 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.
*
* o Neither the name of Freescale Semiconductor, Inc. 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 HOLDER 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.
*/
#ifndef __FSL_PHY_DRIVER_H__
#define __FSL_PHY_DRIVER_H__
#include <stdint.h>
#include <stdbool.h>
#include "fsl_enet_driver.h"
/*!
* @addtogroup phy_driver
* @{
*/
/*! @file*/
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @brief Defines the PHY return status. */
typedef enum _phy_status
{
kStatus_PHY_Success = 0, /*!< Success*/
kStatus_PHY_InvaildInput = 1, /*!< Invalid PHY input parameter*/
kStatus_PHY_TimeOut = 2, /*!< PHY timeout*/
kStatus_PHY_Fail = 3 /*!< PHY fail*/
} phy_status_t;
/*! @brief Defines the ENET timeout.*/
typedef enum _phy_timeout
{
kPhyTimeout = 0x10000, /*!< ENET resets timeout.*/
} phy_timeout_t;
/*! @brief Defines the PHY register.*/
typedef enum _enet_phy_register
{
kEnetPhyCR = 0, /*!< PHY control register */
kEnetPhySR = 1, /*!< PHY status register*/
kEnetPhyId1 = 2, /*!< PHY identification register 1*/
kEnetPhyId2 = 3, /*!< PHY identification register 2*/
kEnetPhyCt2 = 0x1e /*!< PHY control2 register*/
} enet_phy_register_t;
/*! @brief Defines the control flag.*/
typedef enum _enet_phy_control
{
kEnetPhyAutoNeg = 0x1000,/*!< ENET PHY auto negotiation control*/
kEnetPhySpeed = 0x2000, /*! ENET PHY speed control*/
kEnetPhyLoop = 0x4000, /*!< ENET PHY loop control*/
kEnetPhyReset = 0x8000, /*!< ENET PHY reset control*/
kEnetPhy10HalfDuplex = 0x01, /*!< ENET PHY 10 M half duplex*/
kEnetPhy100HalfDuplex = 0x02,/*!< ENET PHY 100 M half duplex*/
kEnetPhy10FullDuplex = 0x05,/*!< ENET PHY 10 M full duplex*/
kEnetPhy100FullDuplex = 0x06/*!< ENET PHY 100 M full duplex*/
} enet_phy_control_t;
/*! @brief Defines the PHY link speed. */
typedef enum _enet_phy_speed
{
kEnetSpeed10M = 0, /*!< ENET PHY 10 M speed*/
kEnetSpeed100M = 1 /*!< ENET PHY 100 M speed*/
} enet_phy_speed_t;
/*! @brief Defines the PHY link duplex.*/
typedef enum _enet_phy_duplex
{
kEnetHalfDuplex = 0, /*!< ENET PHY half duplex*/
kEnetFullDuplex = 1 /*!< ENET PHY full duplex*/
} enet_phy_duplex_t;
/*! @brief Defines the PHY status.*/
typedef enum _enet_phy_status
{
kEnetPhyLinkStatus = 0x4, /*!< ENET PHY link status bit*/
kEnetPhyAutoNegAble = 0x08, /*!< ENET PHY auto negotiation ability*/
kEnetPhyAutoNegComplete = 0x20, /*!< ENET PHY auto negotiation complete*/
kEnetPhySpeedDulpexMask = 0x07 /*!< ENET PHY speed mask on status register 2*/
} enet_phy_status_t;
/*! @brief Defines the basic PHY application.*/
typedef struct ENETPhyApi
{
uint32_t (* phy_auto_discover)(enet_dev_if_t * enetIfPtr);/*!< PHY auto discover*/
uint32_t (* phy_init)(enet_dev_if_t * enetIfPtr);/*!< PHY initialize*/
uint32_t (* phy_get_link_speed)(enet_dev_if_t * enetIfPtr, enet_phy_speed_t *speed);/*!< Get PHY speed*/
uint32_t (* phy_get_link_status)(enet_dev_if_t * enetIfPtr, bool *status);/*! Get PHY link status*/
uint32_t (* phy_get_link_duplex)(enet_dev_if_t * enetIfPtr, enet_phy_duplex_t *duplex);/*!< Get PHY link duplex*/
} enet_phy_api_t;
/*******************************************************************************
* Global variables
******************************************************************************/
extern const enet_phy_api_t g_enetPhyApi;
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif
/*!
* @name PHY Driver
* @{
*/
/*!
* @brief Initializes PHY.
*
* @param enetIfPtr The ENET context structure.
* @return The execution status.
*/
uint32_t phy_init(enet_dev_if_t * enetIfPtr);
/*!
* @brief PHY address auto discover.
*
* @param enetIfPtr The ENET context structure.
* @return The execution status.
*/
uint32_t phy_auto_discover(enet_dev_if_t * enetIfPtr);
/*!
* @brief Gets the PHY link speed.
*
* @param enetIfPtr The ENET context structure.
* @param status The link speed of PHY.
* @return The execution status.
*/
uint32_t phy_get_link_speed(enet_dev_if_t * enetIfPtr, enet_phy_speed_t *status);
/*!
* @brief Gets the PHY link status.
*
* @param enetIfPtr The ENET context structure.
* @param status The link on or down status of the PHY.
* @return The execution status.
*/
uint32_t phy_get_link_status(enet_dev_if_t * enetIfPtr, bool *status);
/*!
* @brief Gets the PHY link duplex.
*
* @param enetIfPtr The ENET context structure.
* @param status The link duplex status of PHY.
* @return The execution status.
*/
uint32_t phy_get_link_duplex(enet_dev_if_t * enetIfPtr, enet_phy_duplex_t *status);
/* @} */
#if defined(__cplusplus)
extern }
#endif
/*! @}*/
#endif /* __FSL_PHY_DRIVER_H__ */
/*******************************************************************************
* EOF
******************************************************************************/

View File

@ -0,0 +1,947 @@
/*
* Copyright (c) 2013 - 2014, Freescale Semiconductor, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o 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.
*
* o Neither the name of Freescale Semiconductor, Inc. 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 HOLDER 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.
*/
#ifndef __FSL_ENET_DRIVER_H__
#define __FSL_ENET_DRIVER_H__
#include <stdint.h>
#include <stdbool.h>
#include "fsl_enet_hal.h"
#include "fsl_os_abstraction.h"
/*!
* @addtogroup enet_driver
* @{
*/
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @brief Defines the approach: ENET interrupt handler do receive */
#define ENET_RECEIVE_ALL_INTERRUPT 0
/*! @brief Defines the statistic enable macro.*/
#define ENET_ENABLE_DETAIL_STATS 0
/*! @brief Defines the alignment operation.*/
#define ENET_ALIGN(x,align) ((unsigned int)((x) + ((align)-1)) & (unsigned int)(~(unsigned int)((align)- 1)))
#if FSL_FEATURE_ENET_SUPPORT_PTP
/*! @brief Defines the PTP IOCTL macro.*/
typedef enum _enet_ptp_ioctl
{
kEnetPtpGetRxTimestamp = 0, /*!< ENET PTP gets receive timestamp*/
kEnetPtpGetTxTimestamp, /*!< ENET PTP gets transmit timestamp*/
kEnetPtpGetCurrentTime, /*!< ENET PTP gets current time*/
kEnetPtpSetCurrentTime, /*!< ENET PTP sets current time*/
kEnetPtpFlushTimestamp, /*!< ENET PTP flushes timestamp*/
kEnetPtpCorrectTime, /*!< ENET PTP time correction*/
kEnetPtpSendEthernetPtpV2, /*!< ENET PTPv2 sends Ethernet frame*/
kEnetPtpReceiveEthernetPtpV2 /*!< ENET PTPv2 receives with Ethernet frame*/
} enet_ptp_ioctl_t;
/*! @brief Defines the PTP message buffer number.*/
typedef enum _enet_ptp_buffer_number
{
kEnetPtpL2bufferNumber = 10, /*!< PTP layer2 frame buffer number*/
kEnetPtpRingNumber = 25 /*!< PTP Ring buffer number*/
} enet_ptp_buffer_number_t;
/*! @brief Defines the ENET PTP message related constant.*/
typedef enum _enet_ptp_event_type
{
kEnetPtpSourcePortIdLen = 10, /*!< PTP message sequence id length*/
kEnetPtpEventMsgType = 3, /*!< PTP event message type*/
kEnetPtpEventPort = 319, /*!< PTP event port number*/
kEnetPtpGnrlPort = 320 /*!< PTP general port number*/
} enet_ptp_event_type_t;
/*! @brief Defines all ENET PTP content offsets in the IPv4 PTP UDP/IP multicast message.*/
typedef enum _enet_ipv4_ptp_content_offset
{
kEnetPtpIpVersionOffset = 0xe, /*!< IPv4 PTP message IP version offset*/
kEnetPtpUdpProtocolOffset = 0x17,/*!< IPv4 PTP message UDP protocol offset*/
kEnetPtpUdpPortOffset = 0x24, /*!< IPv4 PTP message UDP port offset*/
kEnetPtpUdpMsgTypeOffset = 0x2a, /*!< IPv4 PTP message UDP message type offset*/
kEnetPtpUdpVersionoffset = 0x2b, /*!< IPv4 PTP message UDP version offset*/
kEnetPtpUdpClockIdOffset = 0x3e, /*!< IPv4 PTP message UDP clock id offset*/
kEnetPtpUdpSequenIdOffset = 0x48,/*!< IPv4 PTP message UDP sequence id offset*/
kEnetPtpUdpCtlOffset = 0x4a /*!< IPv4 PTP message UDP control offset*/
} enet_ipv4_ptp_content_offset_t;
/*! @brief Defines all ENET PTP content offset in THE IPv6 PTP UDP/IP multicast message.*/
typedef enum _enet_ipv6_ptp_content_offset
{
kEnetPtpIpv6UdpProtocolOffset = 0x14, /*!< IPv6 PTP message UDP protocol offset*/
kEnetPtpIpv6UdpPortOffset = 0x38, /*!< IPv6 PTP message UDP port offset*/
kEnetPtpIpv6UdpMsgTypeOffset = 0x3e, /*!< IPv6 PTP message UDP message type offset*/
kEnetPtpIpv6UdpVersionOffset = 0x3f, /*!< IPv6 PTP message UDP version offset*/
kEnetPtpIpv6UdpClockIdOffset = 0x52, /*!< IPv6 PTP message UDP clock id offset*/
kEnetPtpIpv6UdpSequenceIdOffset = 0x5c,/*!< IPv6 PTP message UDP sequence id offset*/
kEnetPtpIpv6UdpCtlOffset = 0x5e /*!< IPv6 PTP message UDP control offset*/
} enet_ipv6_ptp_content_offset_t;
/*! @brief Defines all ENET PTP content offset in the PTP Layer2 Ethernet message.*/
typedef enum _enet_ethernet_ptp_content_offset
{
kEnetPtpEtherPktTypeOffset = 0x0c, /*!< PTPv2 message Ethernet packet type offset*/
kEnetPtpEtherMsgTypeOffset = 0x0e, /*!< PTPv2 message Ethernet message type offset*/
kEnetPtpEtherVersionOffset = 0x0f, /*!< PTPv2 message Ethernet version type offset*/
kEnetPtpEtherClockIdOffset = 0x22, /*!< PTPv2 message Ethernet clock id offset*/
kEnetPtpEtherSequenceIdOffset = 0x2c,/*!< PTPv2 message Ethernet sequence id offset*/
kEnetPtpEtherCtlOffset = 0x2e /*!< PTPv2 message Ethernet control offset*/
} enet_ethernet_ptp_content_offset_t;
/*! @brief Defines the 1588 timer parameters.*/
typedef enum _enet_ptp_timer_wrap_period
{
kEnetPtpAtperVaule = 1000000000, /*!< PTP timer wrap around one second */
kEnetBaseIncreaseUnit = 2 /*!< PTP timer adjusts clock and increases value to 2*/
} enet_ptp_timer_wrap_period_t;
#endif
/*! @brief Defines the interrupt source index for the interrupt vector change table.*/
typedef enum _enet_interrupt_number
{
kEnetTstimerInt = 0, /*!< Timestamp interrupt*/
kEnetTsAvailInt, /*!< TS-avail interrupt*/
kEnetWakeUpInt, /*!< Wakeup interrupt*/
kEnetPlrInt, /*!< Plr interrupt*/
kEnetUnInt, /*!< Un interrupt*/
kEnetRlInt, /*!< RL interrupt*/
kEnetLcInt, /*!< LC interrupt*/
kEnetEberrInt, /*!< Eberr interrupt*/
kEnetMiiInt, /*!< MII interrupt*/
kEnetRxbInt , /*!< Receive byte interrupt*/
kEnetRxfInt, /*!< Receive frame interrupt*/
kEnetTxbInt, /*!< Transmit byte interrupt*/
kEnetTxfInt, /*!< Transmit frame interrupt*/
kEnetGraInt, /*!< Gra interrupt*/
kEnetBabtInt, /*!< Babt interrupt*/
kEnetBabrInt, /*!< Babr interrupt*/
kEnetIntNum /*!< Interrupt number*/
} enet_interrupt_number_t;
/*! @brief Defines the ENET main constant.*/
typedef enum _enet_frame_max
{
kEnetMaxTimeout = 0x10000, /*!< Maximum timeout*/
kEnetMaxFrameSize = 1518, /*!< Maximum frame size*/
kEnetMaxFrameVlanSize = 1522, /*!< Maximum VLAN frame size*/
kEnetMaxFrameDateSize = 1500, /*!< Maximum frame data size*/
kEnetMaxFrameBdNumbers = 7, /*!< Maximum buffer descriptor numbers of a frame*/
kEnetFrameFcsLen = 4, /*!< FCS length*/
kEnetEthernetHeadLen = 14 /*!< Ethernet Frame header length*/
} enet_frame_max_t;
/*! @brief Defines the CRC data for a hash value calculation.*/
typedef enum _enet_crc_parameter
{
kEnetCrcData = 0xFFFFFFFFU, /*!< CRC-32 maximum data */
kEnetCrcOffset = 8, /*!< CRC-32 offset2*/
kEnetCrcMask1 = 0x3F /*!< CRC-32 mask*/
} enet_crc_parameter_t;
/*! @brief Defines the ENET protocol type and main parameters.*/
typedef enum _enet_protocol_type
{
kEnetProtocolIeee8023 = 0x88F7, /*!< Packet type Ethernet ieee802.3*/
kEnetProtocolIpv4 = 0x0800, /*!< Packet type IPv4*/
kEnetProtocolIpv6 = 0x86dd, /*!< Packet type IPv6*/
kEnetProtocol8021QVlan = 0x8100, /*!< Packet type VLAN*/
kEnetPacketUdpVersion = 0x11, /*!< UDP protocol type*/
kEnetPacketIpv4Version = 0x4, /*!< Packet IP version IPv4*/
kEnetPacketIpv6Version = 0x6 /*!< Packet IP version IPv6*/
} enet_protocol_type_t;
/*! @brief Defines the ENET MAC control Configure*/
typedef enum _enet_mac_control_flag
{
kEnetSleepModeEnable = 0x1, /*!< ENET control sleep mode Enable*/
kEnetPayloadlenCheckEnable = 0x2, /*!< ENET receive payload length check Enable*/
kEnetRxFlowControlEnable = 0x4, /*!< ENET flow control, receiver detects PAUSE frames and stops transmitting data when a PAUSE frame is detected*/
kEnetRxCrcFwdEnable = 0x8, /*!< Received frame crc is stripped from the frame*/
kEnetRxPauseFwdEnable = 0x10,/*!< Pause frames are forwarded to the user application*/
kEnetRxPadRemoveEnable = 0x20, /*!< Padding is removed from received frames*/
kEnetRxBcRejectEnable = 0x40, /*!< Broadcast frame reject*/
kEnetRxPromiscuousEnable = 0x80, /*!< Promiscuous mode enabled*/
kEnetRxMiiLoopback = 0x100, /*!< MAC MII loopback mode*/
} enet_mac_control_flag_t;
/*! @brief Defines the multicast group structure for the ENET device. */
typedef struct ENETMulticastGroup
{
enetMacAddr groupAdddr; /*!< Multicast group address*/
uint32_t hash; /*!< Hash value of the multicast group address*/
struct ENETMulticastGroup *next; /*!< Pointer of the next group structure*/
struct ENETMulticastGroup *prv; /*!< Pointer of the previous structure*/
} enet_multicast_group_t;
/*! @brief Defines the receive buffer descriptor configure structure.*/
typedef struct ENETRxBdConfig
{
uint8_t *rxBdPtrAlign; /*!< Aligned receive buffer descriptor pointer */
uint8_t *rxBufferAlign; /*!< Aligned receive data buffer pointer */
uint8_t *rxLargeBufferAlign; /*!< Aligned receive large data buffer pointer*/
uint8_t rxBdNum; /*!< Aligned receive buffer descriptor pointer*/
uint8_t rxBufferNum; /*!< Receive buffer number*/
uint8_t rxLargeBufferNum; /*!< Large receive buffer number*/
uint32_t rxLargeBufferSizeAlign; /*!< Aligned large receive buffer size*/
}enet_rxbd_config_t;
/*! @brief Defines the transmit buffer descriptor configure structure.*/
typedef struct ENETTxBdConfig
{
uint8_t *txBdPtrAlign; /*!< Aligned transmit buffer descriptor pointer*/
uint8_t *txBufferAlign; /*!< Aligned transmit buffer descriptor pointer*/
uint8_t txBufferNum; /*!< Transmit buffer number*/
uint32_t txBufferSizeAlign; /*!< Aligned transmit buffer size*/
}enet_txbd_config_t;
/*! @brief Defines the basic configuration structure for the ENET device.*/
typedef struct ENETMacConfig
{
uint16_t rxBufferSize; /*!< Receive buffer size*/
uint16_t rxLargeBufferNumber; /*!< Receive large buffer number; Needed only when the BD size is smaller than the maximum frame length.*/
uint16_t rxBdNumber; /*!< Receive buffer descriptor number*/
uint16_t txBdNumber; /*!< Transmit buffer descriptor number*/
enetMacAddr macAddr; /*!< MAC hardware address*/
enet_config_rmii_t rmiiCfgMode;/*!< RMII configure mode*/
enet_config_speed_t speed; /*!< Speed configuration*/
enet_config_duplex_t duplex; /*!< Duplex configuration*/
/*!< Mac control configure, it is recommended to use enet_mac_control_flag_t
it is special control set for loop mode, sleep mode, crc forward/terminate etc*/
uint32_t macCtlConfigure;
bool isTxAccelEnabled;/*!< Switcher to enable transmit accelerator*/
bool isRxAccelEnabled;/*!< Switcher to enable receive accelerator*/
bool isStoreAndFwEnabled; /*!< Switcher to enable store and forward*/
enet_config_rx_accelerator_t rxAcceler; /*!< Receive accelerator configure*/
enet_config_tx_accelerator_t txAcceler; /*!< Transmit accelerator configure*/
bool isVlanEnabled; /*!< Switcher to enable VLAN frame*/
bool isPhyAutoDiscover;/*!< Switcher to use PHY auto discover*/
uint32_t miiClock; /*!< MII speed*/
#if FSL_FEATURE_ENET_SUPPORT_PTP
uint16_t ptpRingBufferNumber; /*!< PTP ring buffer number*/
bool isSlaveModeEnabled; /*!< PTP timer configuration*/
#endif
} enet_mac_config_t;
/*! @brief Defines the basic configuration for PHY.*/
typedef struct ENETPhyConfig
{
uint8_t phyAddr; /*!< PHY address*/
bool isLoopEnabled; /*!< Switcher to enable the HY loop mode*/
} enet_phy_config_t;
#if FSL_FEATURE_ENET_SUPPORT_PTP
/*! @brief Defines the ENET Mac PTP timestamp structure.*/
typedef struct ENETMacPtpTime
{
uint64_t second; /*!< Second*/
uint32_t nanosecond; /*!< Nanosecond*/
} enet_mac_ptp_time_t;
/*! @brief Defines the ENET PTP timer drift structure.*/
typedef struct ENETPtpDrift
{
int32_t drift; /*!< Drift for the PTP timer to adjust*/
} enet_ptp_drift_t;
/*! @brief Defines the ENET MAC PTP time parameter.*/
typedef struct ENETPtpMasterTimeData
{
uint8_t masterPtpInstance;/*!< PTP master timer instance*/
uint64_t second; /*!< PTP master timer second */
} enet_ptp_master_time_data_t;
/*! @brief Defines the structure for the ENET PTP message data and timestamp data.*/
typedef struct ENETMacPtpTsData
{
uint8_t version; /*!< PTP version*/
uint8_t sourcePortId[kEnetPtpSourcePortIdLen];/*!< PTP source port ID*/
uint16_t sequenceId; /*!< PTP sequence ID*/
uint8_t messageType; /*!< PTP message type*/
enet_mac_ptp_time_t timeStamp;/*!< PTP timestamp*/
} enet_mac_ptp_ts_data_t;
/*! @brief Defines the ENET PTP ring buffer structure for the PTP message timestamp store.*/
typedef struct ENETMacPtpTsRing
{
uint32_t front; /*!< The first index of the ring*/
uint32_t end; /*!< The end index of the ring*/
uint32_t size; /*!< The size of the ring*/
enet_mac_ptp_ts_data_t *ptpTsDataPtr;/*!< PTP message data structure*/
} enet_mac_ptp_ts_ring_t;
/*! @brief Defines the ENET packet for the PTP version2 message using the layer2 Ethernet frame.*/
typedef struct ENETPtpL2packet
{
uint8_t packet[kEnetMaxFrameDateSize]; /*!< Buffer for ptpv2 message*/
uint16_t length; /*!< PTP message length*/
} enet_ptp_l2packet_t;
/*! @brief Defines the ENET PTPv2 packet queue using the layer2 Ethernet frame.*/
typedef struct ENETPtpL2queue
{
enet_ptp_l2packet_t l2Packet[kEnetPtpL2bufferNumber]; /*!< PTP layer2 packet*/
uint16_t writeIdex; /*!< Queue write index*/
uint16_t readIdx; /*!< Queue read index*/
} enet_ptp_l2queue_t;
/*! @brief Defines the ENET PTP layer2 Ethernet frame structure.*/
typedef struct ENETPtpL2Ethernet
{
uint8_t *ptpMsg; /*!< PTP message*/
uint16_t length; /*!< Length of the PTP message*/
enetMacAddr hwAddr; /*!< Destination hardware address*/
} enet_ptp_l2_ethernet_t;
/*! @brief Defines the ENET PTP buffer structure for all 1588 data.*/
typedef struct ENETPrivatePtpBuffer
{
enet_mac_ptp_ts_ring_t rxTimeStamp;/*!< Data structure for receive message*/
enet_mac_ptp_ts_ring_t txTimeStamp;/*!< Data structure for transmit timestamp*/
enet_ptp_l2queue_t *l2QueuePtr; /*!< Data structure for layer2 Ethernet queue*/
uint64_t masterSecond; /*!< PTP time second when it's master time*/
} enet_private_ptp_buffer_t;
#endif
/*! @brief Defines the ENET header structure. */
typedef struct ENETEthernetHeader
{
enetMacAddr destAddr; /*!< Destination address */
enetMacAddr sourceAddr;/*!< Source address*/
uint16_t type; /*!< Protocol type*/
} enet_ethernet_header_t;
/*! @brief Defines the ENET VLAN frame header structure. */
typedef struct ENET8021vlanHeader
{
enetMacAddr destAddr; /*!< Destination address */
enetMacAddr sourceAddr;/*!< Source address*/
uint16_t tpidtag; /*!< ENET 8021tag header tag region*/
uint16_t othertag; /*!< ENET 8021tag header type region*/
uint16_t type; /*!< Protocol type*/
} enet_8021vlan_header_t;
/*! @brief Defines the ENET MAC context structure for the buffer address, buffer descriptor address, etc.*/
typedef struct ENETMacContext
{
uint8_t *rxBufferPtr; /*!< Receive buffer pointer*/
uint8_t *rxLargeBufferPtr; /*!< Receive large buffer descriptor*/
uint8_t *txBufferPtr; /*!< Transmit buffer pointer*/
uint8_t *rxBdBasePtr; /*!< Receive buffer descriptor base address pointer*/
uint8_t *rxBdCurPtr; /*!< Current receive buffer descriptor pointer*/
uint8_t *rxBdDirtyPtr; /*!< Receive dirty buffer descriptor*/
uint8_t *txBdBasePtr; /*!< Transmit buffer descriptor base address pointer*/
uint8_t *txBdCurPtr; /*!< Current transmit buffer descriptor pointer*/
uint8_t *txBdDirtyPtr; /*!< Last cleaned transmit buffer descriptor pointer*/
bool isTxFull; /*!< Transmit buffer descriptor full*/
bool isRxFull; /*!< Receive buffer descriptor full*/
uint32_t bufferdescSize; /*!< ENET buffer descriptor size*/
uint16_t rxBufferSizeAligned; /*!< Receive buffer alignment size*/
#if FSL_FEATURE_ENET_SUPPORT_PTP
enet_private_ptp_buffer_t privatePtp;/*!< PTP private buffer*/
#endif
} enet_mac_context_t;
/*! @brief Defines the ENET packets statistic structure.*/
typedef struct ENETMacStats
{
uint32_t statsRxTotal; /*!< Total number of receive packets*/
uint32_t statsRxMissed; /*!< Total number of receive packets*/
uint32_t statsRxDiscard; /*!< Receive discarded with error */
uint32_t statsRxError; /*!< Receive discarded with error packets*/
uint32_t statsTxTotal; /*!< Total number of transmit packets*/
uint32_t statsTxMissed; /*!< Transmit missed*/
uint32_t statsTxDiscard; /*!< Transmit discarded with error */
uint32_t statsTxError; /*!< Transmit error*/
uint32_t statsRxAlign; /*!< Receive non-octet alignment*/
uint32_t statsRxFcs; /*!< Receive CRC error*/
uint32_t statsRxTruncate;/*!< Receive truncate*/
uint32_t statsRxLengthGreater; /*!< Receive length greater than RCR[MAX_FL] */
uint32_t statsRxCollision; /*!< Receive collision*/
uint32_t statsRxOverRun; /*!< Receive over run*/
uint32_t statsTxOverFlow; /*!< Transmit overflow*/
uint32_t statsTxLateCollision; /*!< Transmit late collision*/
uint32_t statsTxExcessCollision;/*!< Transmit excess collision*/
uint32_t statsTxUnderFlow; /*!< Transmit under flow*/
uint32_t statsTxLarge; /*!< Transmit large packet*/
uint32_t statsTxSmall; /*!< Transmit small packet*/
} enet_stats_t;
/*! @brief Defines the ENET MAC packet buffer structure.*/
typedef struct ENETMacPacketBuffer
{
uint8_t *data;
uint16_t length;
} enet_mac_packet_buffer_t;
#if ENET_RECEIVE_ALL_INTERRUPT
typedef uint32_t (* enet_netif_callback_t)(void *enetPtr, enet_mac_packet_buffer_t *packetBuffer);
#endif
/*! @brief Defines the ENET device data structure for the ENET.*/
typedef struct ENETDevIf
{
struct ENETDevIf *next; /*!< Next device structure address*/
void *netIfPtr; /*!< Store the connected upper layer in the structure*/
#if ENET_RECEIVE_ALL_INTERRUPT
void *enetNetifService; /*!< Service function*/
#endif
enet_multicast_group_t *multiGroupPtr; /*!< Multicast group chain*/
uint32_t deviceNumber; /*!< Device number*/
bool isInitialized; /*!< Device initialized*/
uint16_t maxFrameSize; /*!< MAC maximum frame size*/
enet_mac_config_t *macCfgPtr;/*!< MAC configuration structure*/
enet_phy_config_t *phyCfgPtr;/*!< PHY configuration structure*/
const struct ENETMacApi *macApiPtr; /*!< MAC application interface structure*/
void *phyApiPtr; /*!< PHY application interface structure*/
enet_mac_context_t *macContextPtr; /*!< MAC context pointer*/
#if ENET_ENABLE_DETAIL_STATS
enet_stats_t stats; /*!< Packets statistic*/
#endif
#if ENET_RECEIVE_ALL_INTERRUPT
enet_netif_callback_t enetNetifcall; /*!< Receive callback function to the upper layer*/
#else
event_object_t enetReceiveSync; /*!< Receive sync signal*/
#endif
lock_object_t enetContextSync; /*!< Sync signal*/
} enet_dev_if_t;
/*! @brief Defines the basic application for the ENET device.*/
typedef struct ENETMacApi
{
uint32_t (* enet_mac_init)(enet_dev_if_t * enetIfPtr, enet_rxbd_config_t *rxbdCfg, enet_txbd_config_t *txbdCfg);/*!< MAC initialize interface*/
uint32_t (* enet_mac_deinit)(enet_dev_if_t * enetIfPtr);/*!< MAC close interface*/
uint32_t (* enet_mac_send)(enet_dev_if_t * enetIfPtr, uint8_t *packet, uint32_t size);/*!< MAC send packets*/
#if !ENET_RECEIVE_ALL_INTERRUPT
uint32_t (* enet_mac_receive)(enet_dev_if_t * enetIfPtr, enet_mac_packet_buffer_t *packBuffer);/*!< MAC receive interface*/
#endif
uint32_t (* enet_mii_read)(uint32_t instance, uint32_t phyAddr, uint32_t phyReg, uint32_t *dataPtr);/*!< MII reads PHY*/
uint32_t (* enet_mii_write)(uint32_t instance, uint32_t phyAddr, uint32_t phyReg, uint32_t data);/*!< MII writes PHY*/
uint32_t (* enet_add_multicast_group)(uint32_t instance, enet_multicast_group_t *multiGroupPtr, uint8_t *groupAddr);/*!< Add multicast group*/
uint32_t (* enet_leave_multicast_group)(uint32_t instance, enet_multicast_group_t *multiGroupPtr, uint8_t *groupAddr);/*!< Leave multicast group*/
} enet_mac_api_t;
/*******************************************************************
* Global variables
***********************************************************************/
extern const enet_mac_api_t g_enetMacApi;
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif
/*!
* @name ENET Driver
* @{
*/
#if FSL_FEATURE_ENET_SUPPORT_PTP
/*!
* @brief Initializes the ENET PTP context structure with the basic configuration.
*
* @param macContextPtr The pointer to the ENET MAC macContext structure.
* @return The execution status.
*/
uint32_t enet_ptp_init(enet_private_ptp_buffer_t *privatePtpPtr, uint32_t ptpRxBufferNum, enet_mac_ptp_ts_data_t *ptpTsRxDataPtr, uint32_t ptpTxBufferNum, enet_mac_ptp_ts_data_t *ptpTsTxDataPtr);
/*!
* @brief Initializes the ENET PTP timer with the basic configuration.
*
* After the PTP starts, the 1588 timer also starts running. If the user wants the 1588 timer
* as the slave, enable the isSlaveEnabled flag.
*
* @param instance The ENET instance number.
* @param ptpCfgPtr The pointer to the basic PTP timer configuration structure.
* @return The execution status.
*/
uint32_t enet_ptp_start(uint32_t instance, bool isSlaveEnabled);
/*!
* @brief Parses the ENET packet.
*
* Parses the ENET message and checks if it is a PTP message. If it is a PTP message,
* the message is stored in the PTP information structure. Message parsing
* decides whether timestamp processing is done after that.
*
* @param packet The ENET packet.
* @param ptpTsPtr The pointer to the PTP data structure.
* @param isPtpMsg The PTP message flag.
* @param isFastEnabled The fast operation flag. If set, only check if it is a ptp message
* and doesn't store any ptp message.
* @return The execution status.
*/
uint32_t enet_ptp_parse(uint8_t *packet, enet_mac_ptp_ts_data_t *ptpTsPtr, bool *isPtpMsg, bool isFastEnabled);
/*!
* @brief Gets the current value of the ENET PTP time.
*
* @param ptpTimerPtr The PTP timer structure.
* @return The execution status.
*/
uint32_t enet_ptp_get_time(enet_mac_ptp_time_t *ptpTimerPtr);
/*!
* @brief Sets the current value of the ENET PTP time.
*
* @param ptpTimerPtr The PTP timer structure.
* @return The execution status.
*/
uint32_t enet_ptp_set_time(enet_mac_ptp_time_t *ptpTimerPtr);
/*!
* @brief Adjusts the ENET PTP time.
*
* @param instance The ENET instance number.
* @param drift The PTP timer drift value.
* @return The execution status.
*/
uint32_t enet_ptp_correction_time(uint32_t instance, int32_t drift);
/*!
* @brief Stores the transmit timestamp.
*
* @param ptpBuffer The PTP buffer pointer.
* @param bdPtr The current transmit buffer descriptor.
* @return The execution status.
*/
uint32_t enet_ptp_store_tx_timestamp(enet_private_ptp_buffer_t *ptpBuffer,void *bdPtr);
/*!
* @brief Stores receive timestamp.
*
* @param ptpBuffer The PTP buffer pointer.
* @param packet The current receive packet.
* @param bdPtr The current receive buffer descriptor.
* @return The execution status.
*/
uint32_t enet_ptp_store_rx_timestamp(enet_private_ptp_buffer_t *ptpBuffer, uint8_t *packet, void *bdPtr);
/*!
* @brief Initializes the buffer queue for the PTP layer2 Ethernet packets.
*
* @param ptpBuffer The PTP buffer pointer.
* @return The execution status.
*/
uint32_t enet_ptp_l2queue_init(enet_private_ptp_buffer_t *ptpBuffer, enet_ptp_l2queue_t *ptpL2QuePtr);
/*!
* @brief Adds the PTP layer2 Ethernet packet to the PTP Ethernet packet queue.
*
* @param ptpQuePtr The ENET private ptp layer2 buffer queue structure pointer.
* @param packet The packet buffer pointer.
* @param length The packet length.
* @return The execution status.
*/
uint32_t enet_ptp_service_l2packet(enet_ptp_l2queue_t * ptpQuePtr, uint8_t *packet, uint16_t length);
/*!
* @brief Sends the PTP layer2 Ethernet packet to the Net.
*
* @param enetIfPtr The ENET context structure.
* @param paramPtr The buffer from upper layer.
* @return The execution status.
*/
uint32_t enet_ptp_send_l2packet(enet_dev_if_t * enetIfPtr, void *paramPtr);
/*!
* @brief Receives the PTP layer2 Ethernet packet from the Net.
*
* @param enetIfPtr The ENET context structure.
* @param paramPtr The buffer receive from net and will send to upper layer.
* @return The execution status.
*/
uint32_t enet_ptp_receive_l2packet(enet_dev_if_t * enetIfPtr,void *paramPtr);
/*!
* @brief Provides the handler for the 1588 stack to do PTP IOCTL.
*
* @param enetIfPtr The ENET context structure.
* @param commandId The command id.
* @param inOutPtr The data buffer.
* @return The execution status.
*/
uint32_t enet_ptp_ioctl(enet_dev_if_t * enetIfPtr, uint32_t commandId, void *inOutPtr);
/*!
* @brief Stops the ENET PTP timer.
*
* @param instance The ENET instance number.
* @return The execution status.
*/
uint32_t enet_ptp_stop(uint32_t instance);
/*!
* @brief Checks whether the PTP ring buffer is full.
*
* @param ptpTsRingPtr The ENET PTP timestamp ring.
* @return True if the PTP ring buffer is full. Otherwise, false.
*/
bool enet_ptp_ring_is_full(enet_mac_ptp_ts_ring_t *ptpTsRingPtr);
/*!
* @brief Updates the latest ring buffers.
*
* Adds the PTP message data to the PTP ring buffers and increases the
* PTP ring buffer index.
*
* @param ptpTsRingPtr The ENET PTP timestamp ring.
* @param data The PTP data buffer.
* @return The execution status.
*/
uint32_t enet_ptp_ring_update(enet_mac_ptp_ts_ring_t *ptpTsRingPtr, enet_mac_ptp_ts_data_t *data);
/*!
* @brief Searches the element in ring buffers with the message ID and Clock ID.
*
* @param ptpTsRingPtr The ENET PTP timestamp ring.
* @param data The PTP data buffer.
* @return The execution status.
*/
uint32_t enet_ptp_ring_search(enet_mac_ptp_ts_ring_t *ptpTsRingPtr, enet_mac_ptp_ts_data_t *data);
/*!
* @brief Calculates the ENET PTP ring buffer index.
*
* @param size The ring size.
* @param curIdx The current ring index.
* @param offset The offset index.
* @return The execution status.
*/
static inline uint32_t enet_ptp_ring_index(uint32_t size, uint32_t curIdx, uint32_t offset)
{
return ((curIdx + offset) % size);
}
/*!
* @brief Frees all ring buffers.
*
* @param enetContextPtr The ENET MAC context buffer.
* @return The execution status.
*/
uint32_t enet_ptp_deinit(enet_mac_context_t *enetContextPtr);
/*!
* @brief The ENET PTP time interrupt handler.
*
* @param enetIfPtr The ENET context structure pointer.
*/
void enet_mac_ts_isr(void *enetIfPtr);
#endif
/*!
* @brief(R)MII Read function.
*
* @param instance The ENET instance number.
* @param phyAddr The PHY address.
* @param phyReg The PHY register.
* @param dataPtr The data read from MII.
* @return The execution status.
*/
uint32_t enet_mii_read(uint32_t instance, uint32_t phyAddr, uint32_t phyReg, uint32_t *dataPtr);
/*!
* @brief(R)MII Read function.
*
* @param instance The ENET instance number.
* @param phyAddr The PHY address.
* @param phyReg The PHY register.
* @param data The data write to MII.
* @return The execution status.
*/
uint32_t enet_mii_write(uint32_t instance, uint32_t phyAddr, uint32_t phyReg, uint32_t data);
/*!
* @brief Initializes ENET buffer descriptors.
*
* @param enetIfPtr The ENET context structure.
* @return The execution status.
*/
uint32_t enet_mac_bd_init(enet_dev_if_t * enetIfPtr);
/*!
* @brief Initializes the ENET MAC MII(MDC/MDIO) interface.
*
* @param enetIfPtr The ENET context structure.
* @return The execution status.
*/
uint32_t enet_mac_mii_init(enet_dev_if_t * enetIfPtr);
/*!
* @brief Initialize the ENET receive buffer descriptors.
*
* If you open ENET_RECEIVE_ALL_INTERRUPT to do receive
* data buffer numbers can be the same as the receive descriptor numbers.
* But if you close ENET_RECEIVE_ALL_INTERRUPT and choose polling receive
* frames please make sure the receive data buffers are more than
* buffer descriptor numbers to guarantee a good performance.
*
* @param enetIfPtr The ENET context structure.
* @param rxbdCfg The receive buffer descriptor configuration.
* @return The execution status.
*/
uint32_t enet_mac_rxbd_init(enet_dev_if_t * enetIfPtr, enet_rxbd_config_t *rxbdCfg);
/*!
* @brief Deinitialize the ENET receive buffer descriptors.
*
* Deinitialize the ENET receive buffer descriptors.
*
* @param enetIfPtr The ENET context structure.
* @return The execution status.
*/
uint32_t enet_mac_rxbd_deinit(enet_dev_if_t * enetIfPtr);
/*!
* @brief Initialize the ENET transmit buffer descriptors.
*
* @param enetIfPtr The ENET context structure.
* @param txbdCfg The transmit buffer descriptor configuration.
* @return The execution status.
*/
uint32_t enet_mac_txbd_init(enet_dev_if_t * enetIfPtr, enet_txbd_config_t *txbdCfg);
/*!
* @brief Deinitialize the ENET transmit buffer descriptors.
*
* Deinitialize the ENET transmit buffer descriptors.
*
* @param enetIfPtr The ENET context structure.
* @return The execution status.
*/
uint32_t enet_mac_txbd_deinit(enet_dev_if_t * enetIfPtr);
/*!
* @brief Initializes ENET MAC FIFO and accelerator with the basic configuration.
*
* @param enetIfPtr The ENET context structure.
* @return The execution status.
*/
uint32_t enet_mac_configure_fifo_accel(enet_dev_if_t * enetIfPtr);
/*!
* @brief the ENET controller with the basic configuration.
*
* @param enetIfPtr The ENET context structure.
* @return The execution status.
*/
uint32_t enet_mac_configure_controller(enet_dev_if_t * enetIfPtr);
/*!
* @brief Deinit the ENET device.
*
* @param enetIfPtr The ENET context structure.
* @return The execution status.
*/
uint32_t enet_mac_deinit(enet_dev_if_t * enetIfPtr);
#if !ENET_RECEIVE_ALL_INTERRUPT
/*!
* @brief Updates the receive buffer descriptor.
*
* This updates the used receive buffer descriptor ring to
* ensure that the used BDS is correctly used again. It cleans
* the status region and sets the control region of the used receive buffer
* descriptor. If the isBufferUpdate flag is set, the data buffer in the
* buffer descriptor is updated.
*
* @param enetIfPtr The ENET context structure.
* @param isBufferUpdate The data buffer update flag.
* @return The execution status.
*/
uint32_t enet_mac_update_rxbd(enet_dev_if_t * enetIfPtr, bool isBufferUpdate);
#else
/*!
* @brief Updates the receive buffer descriptor.
*
* Clears the status region and sets the control region of the current receive buffer
* descriptor to ensure that it is used correctly again. It increases the buffer
* descriptor index to the next buffer descriptor.
*
* @param enetIfPtr The ENET context structure.
* @return The execution status.
*/
uint32_t enet_mac_update_rxbd(enet_dev_if_t * enetIfPtr);
#endif
/*!
* @brief Processes the ENET receive frame error statistics.
*
* This interface gets the error statistics of the received frame.
* Because the error information is in the last BD of a frame, this interface
* should be called when processing the last BD of a frame.
*
* @param enetIfPtr The ENET context structure.
* @param data The current control and status data of the buffer descriptor.
* @return The frame error status.
* - True if the frame has an error.
* - False if the frame does not have an error.
*/
bool enet_mac_rx_error_stats(enet_dev_if_t * enetIfPtr, uint32_t data);
/*!
* @brief Processes the ENET transmit frame statistics.
*
* This interface gets the error statistics of the transmit frame.
* Because the error information is in the last BD of a frame, this interface
* should be called when processing the last BD of a frame.
*
* @param enetIfPtr The ENET context structure.
* @param curBd The current buffer descriptor.
*/
void enet_mac_tx_error_stats(enet_dev_if_t * enetIfPtr,void *curBd);
/*!
* @brief ENET transmit buffer descriptor cleanup.
*
* First, store the transmit frame error statistic and PTP timestamp of the transmitted packets.
* Second, clean up the used transmit buffer descriptors.
* If the PTP 1588 feature is open, this interface captures the 1588 timestamp.
* It is called by the transmit interrupt handler.
*
* @param enetIfPtr The ENET context structure.
* @return The execution status.
*/
uint32_t enet_mac_tx_cleanup(enet_dev_if_t * enetIfPtr);
#if !ENET_RECEIVE_ALL_INTERRUPT
/*!
* @brief Receives ENET packets.
*
* @param enetIfPtr The ENET context structure.
* @param packBuffer The received data buffer.
* @return The execution status.
*/
uint32_t enet_mac_receive(enet_dev_if_t * enetIfPtr, enet_mac_packet_buffer_t *packBuffer);
#else
/*!
* @brief Receives ENET packets.
*
* @param enetIfPtr The ENET context structure.
* @return The execution status.
*/
uint32_t enet_mac_receive(enet_dev_if_t * enetIfPtr);
#endif
/*!
* @brief Transmits ENET packets.
*
* @param enetIfPtr The ENET context structure.
* @param packet The frame to be transmitted.
* @param size The frame size.
* @return The execution status.
*/
uint32_t enet_mac_send(enet_dev_if_t * enetIfPtr, uint8_t *packet, uint32_t size);
/*!
* @brief The ENET receive interrupt handler.
*
* @param enetIfPtr The ENET context structure pointer.
*/
void enet_mac_rx_isr(void *enetIfPtr);
/*!
* @brief The ENET transmit interrupt handler.
*
* @param enetIfPtr The ENET context structure pointer.
*/
void enet_mac_tx_isr(void *enetIfPtr);
/*!
* @brief Calculates the CRC hash value.
*
* @param address The ENET MAC hardware address.
* @param crcVlaue The calculated CRC value of the Mac address.
*/
void enet_mac_calculate_crc32(enetMacAddr address, uint32_t *crcValue);
/*!
* @brief Adds the ENET device to a multicast group.
*
* @param instance The ENET instance number.
* @param multiGroupPtr The ENET multicast group structure.
* @param address The ENET MAC hardware address.
* @return The execution status.
*/
uint32_t enet_mac_add_multicast_group(uint32_t instance, enet_multicast_group_t *multiGroupPtr, enetMacAddr address);
/*!
* @brief Moves the ENET device from a multicast group.
*
* @param instance The ENET instance number.
* @param multiGroupPtr The ENET multicast group structure.
* @param address The ENET MAC hardware address.
* @return The execution status.
*/
uint32_t enet_mac_leave_multicast_group(uint32_t instance, enet_multicast_group_t *multiGroupPtr, enetMacAddr address);
/*!
* @brief Initializes the ENET with the basic configuration.
*
* @param enetIfPtr The pointer to the basic configuration structure.
* @return The execution status.
*/
uint32_t enet_mac_init(enet_dev_if_t * enetIfPtr, enet_rxbd_config_t *rxbdCfg,
enet_txbd_config_t *txbdCfg);
/*!
* @brief Enqueues a data buffer to the buffer queue.
*
* @param queue The buffer queue.
* @param buffer The buffer to add to the buffer queue.
*/
void enet_mac_enqueue_buffer( void **queue, void *buffer);
/*!
* @brief Dequeues a buffer from the buffer queue.
*
* @param queue The buffer queue.
* @return The dequeued data buffer.
*/
void *enet_mac_dequeue_buffer( void **queue);
/* @} */
#if defined(__cplusplus)
extern }
#endif
/*! @}*/
#endif /* __FSL_ENET_DRIVER_H__ */
/*******************************************************************************
* EOF
******************************************************************************/

View File

@ -0,0 +1,106 @@
/*
* Copyright (c) 2013 - 2014, Freescale Semiconductor, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o 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.
*
* o Neither the name of Freescale Semiconductor, Inc. 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 HOLDER 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.
*/
#include "fsl_enet_driver.h"
#include "fsl_clock_manager.h"
/*******************************************************************************
* Variables
******************************************************************************/
extern void *enetIfHandle;
/* Internal irq number*/
typedef enum _enet_irq_number
{
kEnetTsTimerNumber = 0, /*!< ENET ts_timer irq number*/
kEnetReceiveNumber = 1, /*!< ENET receive irq number*/
kEnetTransmitNumber = 2, /*!< ENET transmit irq number*/
kEnetMiiErrorNumber = 3 /*!< ENET mii error irq number*/
}enet_irq_number_t;
#if FSL_FEATURE_ENET_SUPPORT_PTP
extern enet_ptp_master_time_data_t g_ptpMasterTime;
#if FSL_FEATURE_ENET_PTP_TIMER_CHANNEL_INTERRUPT
#define ENET_TIMER_CHANNEL_NUM 2
#endif
#endif
#if defined (K64F12_SERIES) || defined (K70F12_SERIES)
IRQn_Type enet_irq_ids[HW_ENET_INSTANCE_COUNT][FSL_FEATURE_ENET_INTERRUPT_COUNT] =
{
{ ENET_1588_Timer_IRQn, ENET_Receive_IRQn, ENET_Transmit_IRQn, ENET_Error_IRQn}
};
uint8_t enetIntMap[kEnetIntNum] =
{
kEnetTsTimerNumber,
kEnetTsTimerNumber,
kEnetMiiErrorNumber,
kEnetMiiErrorNumber,
kEnetMiiErrorNumber,
kEnetMiiErrorNumber,
kEnetMiiErrorNumber,
kEnetMiiErrorNumber,
kEnetMiiErrorNumber,
kEnetReceiveNumber,
kEnetReceiveNumber,
kEnetTransmitNumber,
kEnetTransmitNumber,
kEnetMiiErrorNumber,
kEnetMiiErrorNumber,
kEnetMiiErrorNumber
};
#endif
/*******************************************************************************
* Code
******************************************************************************/
#if defined (K64F12_SERIES) || defined (K70F12_SERIES)
void ENET_Transmit_IRQHandler(void)
{
enet_mac_tx_isr(enetIfHandle);
}
void ENET_Receive_IRQHandler(void)
{
enet_mac_rx_isr(enetIfHandle);
}
#if FSL_FEATURE_ENET_SUPPORT_PTP
void ENET_1588_Timer_IRQHandler(void)
{
enet_mac_ts_isr(enetIfHandle);
}
#endif
#endif
/*******************************************************************************
* EOF
******************************************************************************/

View File

@ -0,0 +1,4 @@
ENET_DRIVER_DIR := $(SDK_ROOT)/platform/drivers/enet
SOURCES += $(ENET_DRIVER_DIR)/src/fsl_enet_driver.c \
$(ENET_DRIVER_DIR)/src/fsl_enet_irq.c
INCLUDES += $(ENET_DRIVER_DIR)

View File

@ -0,0 +1,59 @@
/*
* Copyright (c) 2013 - 2014, Freescale Semiconductor, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o 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.
*
* o Neither the name of Freescale Semiconductor, Inc. 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 HOLDER 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.
*/
#ifndef __FSL_INTERRUPT_FEATURES_H__
#define __FSL_INTERRUPT_FEATURES_H__
#if (defined(CPU_MKL25Z32VFM4) || defined(CPU_MKL25Z64VFM4) || defined(CPU_MKL25Z128VFM4) || \
defined(CPU_MKL25Z32VFT4) || defined(CPU_MKL25Z64VFT4) || defined(CPU_MKL25Z128VFT4) || \
defined(CPU_MKL25Z32VLH4) || defined(CPU_MKL25Z64VLH4) || defined(CPU_MKL25Z128VLH4) || \
defined(CPU_MKL25Z32VLK4) || defined(CPU_MKL25Z64VLK4) || defined(CPU_MKL25Z128VLK4))
#define FSL_FEATURE_INTERRUPT_IRQ_MAX (31)
#define FSL_FEATURE_INTERRUPT_IRQ_MIN (-14)
#elif (defined(CPU_MK70FN1M0VMJ12) || defined(CPU_MK70FX512VMJ12) || \
defined(CPU_MK70FN1M0VMJ15) || defined(CPU_MK70FX512VMJ15))
#define FSL_FEATURE_INTERRUPT_IRQ_MAX (105)
#define FSL_FEATURE_INTERRUPT_IRQ_MIN (-14)
#elif (defined(CPU_MK64FX512VDC12) || defined(CPU_MK64FN1M0VDC12) || defined(CPU_MK64FX512VLL12) || \
defined(CPU_MK64FN1M0VLL12) || defined(CPU_MK64FX512VLQ12) || defined(CPU_MK64FN1M0VLQ12) || \
defined(CPU_MK64FX512VMD12) || defined(CPU_MK64FN1M0VMD12))
#define FSL_FEATURE_INTERRUPT_IRQ_MAX (85)
#define FSL_FEATURE_INTERRUPT_IRQ_MIN (-14)
#elif (defined(CPU_MK22FN512VDC12))
#define FSL_FEATURE_INTERRUPT_IRQ_MAX (85)
#define FSL_FEATURE_INTERRUPT_IRQ_MIN (-14)
#else
#error "No valid CPU defined"
#endif
#endif /* __FSL_INTERRUPT_FEATURES_H__*/
/*******************************************************************************
* EOF
******************************************************************************/

View File

@ -0,0 +1,142 @@
/*
* Copyright (c) 2013 - 2014, Freescale Semiconductor, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o 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.
*
* o Neither the name of Freescale Semiconductor, Inc. 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 HOLDER 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.
*/
#if !defined(__FSL_INTERRUPT_MANAGER_H__)
#define __FSL_INTERRUPT_MANAGER_H__
#include <stdint.h>
#include <stdbool.h>
#include <assert.h>
#include "fsl_interrupt_features.h"
#include "device/fsl_device_registers.h"
/*! @addtogroup interrupt_manager*/
/*! @{*/
/*! @file*/
/*******************************************************************************
* Definitions
******************************************************************************/
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif /* __cplusplus*/
/*! @name interrupt_manager APIs*/
/*@{*/
/*!
* @brief Installs an interrupt handler routine for a given IRQ number.
*
* This function lets the application register/replace the interrupt
* handler for a specified IRQ number. The IRQ number is different than the vector
* number. IRQ 0 starts from the vector 16 address. See a chip-specific reference
* manual for details and the startup_MKxxxx.s file for each chip
* family to find out the default interrupt handler for each device. This
* function converts the IRQ number to the vector number by adding 16 to
* it.
*
* @param irqNumber IRQ number
* @param handler Interrupt handler routine address pointer
*/
void interrupt_register_handler(IRQn_Type irqNumber, void (*handler)(void));
/*!
* @brief Enables an interrupt for a given IRQ number.
*
* This function enables the individual interrupt for a specified IRQ
* number. It calls the system NVIC API to access the interrupt control
* register. The input IRQ number does not include the core interrupt, only
* the peripheral interrupt, from 0 to a maximum supported IRQ.
*
* @param irqNumber IRQ number
*/
static inline void interrupt_enable(IRQn_Type irqNumber)
{
/* check IRQ number */
assert(0 <= irqNumber);
assert(irqNumber <= FSL_FEATURE_INTERRUPT_IRQ_MAX);
/* call core API to enable the IRQ*/
NVIC_EnableIRQ(irqNumber);
}
/*!
* @brief Disables an interrupt for a given IRQ number.
*
* This function enables the individual interrupt for a specified IRQ
* number. It calls the system NVIC API to access the interrupt control
* register.
*
* @param irqNumber IRQ number
*/
static inline void interrupt_disable(IRQn_Type irqNumber)
{
/* check IRQ number */
assert(0 <= irqNumber);
assert(irqNumber <= FSL_FEATURE_INTERRUPT_IRQ_MAX);
/* call core API to disable the IRQ*/
NVIC_DisableIRQ(irqNumber);
}
/*!
* @brief Enables system interrupt.
*
* This function enables the global interrupt by calling the core API.
*
*/
void interrupt_enable_global(void);
/*!
* @brief Disable system interrupt.
*
* This function disables the global interrupt by calling the core API.
*
*/
void interrupt_disable_global(void);
/*@}*/
#if defined(__cplusplus)
}
#endif /* __cplusplus*/
/*! @}*/
#endif /* __FSL_INTERRUPT_MANAGER_H__*/
/*******************************************************************************
* EOF
******************************************************************************/

View File

@ -0,0 +1,109 @@
/*
* Copyright (c) 2013 - 2014, Freescale Semiconductor, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o 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.
*
* o Neither the name of Freescale Semiconductor, Inc. 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 HOLDER 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.
*/
#include <assert.h>
#include "fsl_interrupt_manager.h"
#include "cmsis_nvic.h"
/*******************************************************************************
* Definitions
******************************************************************************/
/*!
* @brief Counter to manage the nested callings of global disable/enable interrupt.
*/
uint32_t g_interrupt_disable_count = 0;
/*******************************************************************************
* Code
******************************************************************************/
/*FUNCTION**********************************************************************
*
* Function Name : interrupt_register_handler
* Description : Install an interrupt handler routine for a given IRQ number
* This function will let application to register/replace the interrupt
* handler for specified IRQ number. IRQ number is different with Vector
* number. IRQ 0 will start from Vector 16 address. Refer to reference
* manual for details. Also refer to startup_MKxxxx.s file for each chip
* family to find out the default interrut handler for each device. This
* function will convert the IRQ number to vector number by adding 16 to
* it.
*
*END**************************************************************************/
void interrupt_register_handler(IRQn_Type irqNumber, void (*handler)(void))
{
NVIC_SetVector(irqNumber, (uint32_t)handler);
}
/*FUNCTION**********************************************************************
*
* Function Name : interrupt_enable_global
* Description : Enable system interrupt
* This function will enable the global interrupt by calling the core API
*
*END**************************************************************************/
void interrupt_enable_global(void)
{
/* check and update */
if (g_interrupt_disable_count > 0)
{
g_interrupt_disable_count--;
if (g_interrupt_disable_count > 0)
{
return;
}
/* call core API to enable the global interrupt*/
__enable_irq();
}
}
/*FUNCTION**********************************************************************
*
* Function Name : interrupt_disable_global
* Description : Disnable system interrupt
* This function will disable the global interrupt by calling the core API
*
*END**************************************************************************/
void interrupt_disable_global(void)
{
/* call core API to disable the global interrupt*/
__disable_irq();
/* update counter*/
g_interrupt_disable_count++;
}
/*******************************************************************************
* EOF
******************************************************************************/

View File

@ -0,0 +1,4 @@
INTERRUPT_DRIVER_DIR := $(SDK_ROOT)/platform/drivers/interrupt
SOURCES += $(INTERRUPT_DRIVER_DIR)/src/fsl_interrupt_manager.c
INCLUDES += $(INTERRUPT_DRIVER_DIR)

View File

@ -0,0 +1,240 @@
/*
* Copyright (c) 2013 - 2014, Freescale Semiconductor, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o 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.
*
* o Neither the name of Freescale Semiconductor, Inc. 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 HOLDER 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.
*/
#ifndef __FSL_PIT_DRIVER_H__
#define __FSL_PIT_DRIVER_H__
#include <stdint.h>
#include <stdbool.h>
#include "fsl_pit_hal.h"
/*!
* @addtogroup pit_driver
* @{
*/
/*******************************************************************************
* Definitions
******************************************************************************/
/*!
* @brief PIT timer configuration structure
*
* Define structure PitConfig and use pit_init_channel() to make necessary
* initializations. You may also use remaining functions for PIT configuration.
*
* @note the timer chain feature is not valid in all devices, please check
* fsl_pit_features.h for accurate setting. If it's not valid, the value set here
* will be bypassed inside function pit_init_channel().
*/
typedef struct PitUserConfig {
bool isInterruptEnabled; /*!< Timer interrupt 0-disable/1-enable*/
bool isTimerChained; /*!< Chained with previous timer, 0-not/1-chained*/
uint32_t periodUs; /*!< Timer period in unit of microseconds*/
} pit_user_config_t;
/*! @brief PIT ISR callback function typedef */
typedef void (*pit_isr_callback_t)(void);
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif
/*!
* @name Initialize and Shutdown
* @{
*/
/*!
* @brief Initialize PIT module.
*
* This function must be called before calling all the other PIT driver functions.
* This function un-gates the PIT clock and enables the PIT module. The isRunInDebug
* passed into function will affect all timer channels.
*
* @param isRunInDebug Timers run or stop in debug mode.
* - true: Timers continue to run in debug mode.
* - false: Timers stop in debug mode.
*/
void pit_init_module(bool isRunInDebug);
/*!
* @brief Initialize PIT channel.
*
* This function initialize PIT timers by channel. Pass in timer number and its
* config structure. Timers do not start counting by default after calling this
* function. Function pit_timer_start must be called to start timer counting.
* Call pit_set_timer_period_us to re-set the period.
*
* Here is an example demonstrating how to define a PIT channel config structure:
@code
pit_user_config_t pitTestInit = {
.isInterruptEnabled = true,
// Only takes effect when chain feature is available.
// Otherwise, pass in arbitrary value(true/false).
.isTimerChained = false,
// In unit of microseconds.
.periodUs = 1000,
};
@endcode
*
* @param timer Timer channel number.
* @param config PIT channel configuration structure.
*/
void pit_init_channel(uint32_t timer, const pit_user_config_t * config);
/*!
* @brief Disable PIT module and gate control.
*
* This function disables all PIT interrupts and PIT clock. It then gates the
* PIT clock control. pit_init_module must be called if you want to use PIT again.
*/
void pit_shutdown(void);
/* @} */
/*!
* @name Timer Start and Stop
* @{
*/
/*!
* @brief Start timer counting.
*
* After calling this function, timers load period value, count down to 0 and
* then load the respective start value again. Each time a timer reaches 0,
* it generates a trigger pulse and sets the timeout interrupt flag.
*
* @param timer Timer channel number.
*/
void pit_timer_start(uint32_t timer);
/*!
* @brief Stop timer counting.
*
* This function stops every timer counting. Timers reload their periods
* respectively after the next time they call pit_timer_start.
*
* @param timer Timer channel number.
*/
void pit_timer_stop(uint32_t timer);
/* @} */
/*!
* @name Timer Period
* @{
*/
/*!
* @brief Set timer period in microsecond units.
*
* The period range depends on the frequency of PIT source clock. If the required period
* is out of range, use the lifetime timer, if applicable.
*
* @param timer Timer channel number.
* @param us Timer period in microseconds.
*/
void pit_set_timer_period_us(uint32_t timer, uint32_t us);
/*!
* @brief Read current timer value in microsecond units.
*
* This function returns an absolute time stamp in microsecond units.
* One common use of this function is to measure the running time of a part of
* code. Call this function at both the beginning and end of code; the time
* difference between these two time stamps is the running time (Make sure the
* running time will not exceed the timer period). The time stamp returned is
* up-counting.
*
* @param timer Timer channel number.
* @return Current timer value in microseconds.
*/
uint32_t pit_read_timer_us(uint32_t timer);
#if FSL_FEATURE_PIT_HAS_LIFETIME_TIMER
/*!
* @brief Set lifetime timer period.
*
* Timer 1 must be chained with timer 0 before using the lifetime timer. The period
* range is restricted by "period * pitSourceClock < max of an uint64_t integer",
* or it may cause an overflow and be unable to set the correct period.
*
* @param period Lifetime timer period in microseconds.
*/
void pit_set_lifetime_timer_period_us(uint64_t us);
/*!
* @brief Read current lifetime value in microseconds.
*
* This feature returns an absolute time stamp in microsecond units. The time stamp
* value will not exceed the timer period. The timer is up-counting.
*
* @return Current lifetime timer value in microseconds.
*/
uint64_t pit_read_lifetime_timer_us(void);
#endif /*FSL_FEATURE_PIT_HAS_LIFETIME_TIMER*/
/* @} */
/*!
* @name ISR Callback Function
* @{
*/
/*!
* @brief Register pit isr callback function.
*
* System default ISR interfaces are already defined in fsl_pit_irq.c. Users
* can either edit these ISRs or use this function to register a callback
* function. The default ISR runs the callback function if there is one
* installed.
*
* @param timer Timer channel number.
* @param function Pointer to pit isr callback function.
*/
void pit_register_isr_callback_function(uint32_t timer, pit_isr_callback_t function);
/* @} */
#if defined(__cplusplus)
}
#endif
/*! @}*/
#endif /* __FSL_PIT_DRIVER_H__*/
/*******************************************************************************
* EOF
******************************************************************************/

View File

@ -0,0 +1,242 @@
/*
* Copyright (c) 2013 - 2014, Freescale Semiconductor, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o 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.
*
* o Neither the name of Freescale Semiconductor, Inc. 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 HOLDER 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.
*/
#include "fsl_pit_driver.h"
#include "fsl_clock_manager.h"
#include "fsl_interrupt_manager.h"
/*******************************************************************************
* Variables
******************************************************************************/
/* pit source clock variable which will be updated in pit_init_module. */
uint64_t pitSourceClock;
/* Table to save PIT IRQ enum numbers defined in CMSIS files. This table is
* defined in fsl_pit_irq.c */
extern IRQn_Type pit_irq_ids[FSL_FEATURE_PIT_TIMER_COUNT];
/*******************************************************************************
* Code
******************************************************************************/
/*FUNCTION**********************************************************************
*
* Function Name : pit_init_module
* Description : Initialize PIT module.
* This function must be called before calling all the other PIT driver functions.
* This function un-gates the PIT clock and enables the PIT module. The isRunInDebug
* passed into function will affect all timer channels.
*
*END**************************************************************************/
void pit_init_module(bool isRunInDebug)
{
uint32_t busClock;
/* Un-gate pit clock*/
clock_manager_set_gate(kClockModulePIT, 0U, true);
/* Enable PIT module clock*/
pit_hal_enable();
/* Set timer run or stop in debug mode*/
pit_hal_configure_timer_run_in_debug(isRunInDebug);
/* Finally, update pit source clock frequency.*/
clock_manager_get_frequency(kBusClock, &busClock);
pitSourceClock = (uint64_t)busClock;
}
/*FUNCTION**********************************************************************
*
* Function Name : pit_init_channel
* Description : Initialize PIT channel.
* This function initialize PIT timers by channel. Pass in timer number and its
* config structure. Timers do not start counting by default after calling this
* function. Function pit_timer_start must be called to start timer counting.
* Call pit_set_timer_period_us to re-set the period.
*
*END**************************************************************************/
void pit_init_channel(uint32_t timer, const pit_user_config_t * config)
{
/* Set timer period.*/
pit_set_timer_period_us(timer, config->periodUs);
#if FSL_FEATURE_PIT_HAS_CHAIN_MODE
/* Configure timer chained or not.*/
pit_hal_configure_timer_chain(timer, config->isTimerChained);
#endif
/* Enable or disable interrupt.*/
pit_hal_configure_interrupt(timer, config->isInterruptEnabled);
/* Configure NVIC*/
if (config->isInterruptEnabled)
{
/* Enable PIT interrupt.*/
interrupt_enable(pit_irq_ids[timer]);
}
}
/*FUNCTION**********************************************************************
*
* Function Name : pit_shutdown
* Description : Disable PIT module and gate control
* This function will disable all PIT interrupts and PIT clock. Then gate the
* PIT clock control. pit_init must be called in order to use PIT again.
*
*END**************************************************************************/
void pit_shutdown(void)
{
uint32_t i;
/* Disable all PIT interrupts. */
for (i=0; i < FSL_FEATURE_PIT_TIMER_COUNT; i++)
{
pit_hal_configure_interrupt(i, false);
interrupt_disable(pit_irq_ids[i]);
}
/* Disable PIT module clock*/
pit_hal_disable();
/* Gate PIT clock control*/
clock_manager_set_gate(kClockModulePIT, 0U, false);
}
/*FUNCTION**********************************************************************
*
* Function Name : pit_timer_start
* Description : Start timer counting.
* After calling this function, timers load period value, count down to 0 and
* then load the respective start value again. Each time a timer reaches 0,
* it will generate a trigger pulse and set the timeout interrupt flag.
*
*END**************************************************************************/
void pit_timer_start(uint32_t timer)
{
pit_hal_timer_start(timer);
}
/*FUNCTION**********************************************************************
*
* Function Name : pit_timer_stop
* Description : Stop timer counting.
* This function will stop every timer counting. Timers will reload their periods
* respectively after calling pit_timer_start next time.
*
*END**************************************************************************/
void pit_timer_stop(uint32_t timer)
{
pit_hal_timer_stop(timer);
}
/*FUNCTION**********************************************************************
*
* Function Name : pit_set_timer_period_us
* Description : Set timer period in microseconds unit.
* The period range depends on the frequency of PIT source clock. If required
* period is out the range, try to use lifetime timer if applicable.
*
*END**************************************************************************/
void pit_set_timer_period_us(uint32_t timer, uint32_t us)
{
/* Calculate the count value, assign it to timer counter register.*/
uint32_t count = (uint32_t)(us * pitSourceClock / 1000000U - 1U);
pit_hal_set_timer_period_count(timer, count);
}
/*FUNCTION**********************************************************************
*
* Function Name : pit_read_timer_us
* Description : Read current timer value in microseconds unit.
* This function will return an absolute time stamp in the unit of microseconds.
* One common use of this function is to measure the running time of part of
* code. Just call this function at both the beginning and end of code, the time
* difference between these two time stamp will be the running time (Need to
* make sure the running time will not exceed the timer period). Also, the time
* stamp returned is up-counting.
*
*END**************************************************************************/
uint32_t pit_read_timer_us(uint32_t timer)
{
/* Get current timer count, and reverse it to up-counting.*/
uint64_t currentTime = (~pit_hal_read_timer_count(timer));
/* Convert count numbers to microseconds unit.*/
currentTime = (currentTime * 1000000U) / pitSourceClock;
return (uint32_t)currentTime;
}
#if FSL_FEATURE_PIT_HAS_LIFETIME_TIMER
/*FUNCTION**********************************************************************
*
* Function Name : pit_set_lifetime_timer_period_us
* Description : Set lifetime timer period (Timers must be chained).
* Timer 1 must be chained with timer 0 before using lifetime timer. The period
* range is restricted by "period * pitSourceClock < max of an uint64_t integer",
* or it may cause a overflow and is not able to set correct period.
*
*END**************************************************************************/
void pit_set_lifetime_timer_period_us(uint64_t us)
{
uint64_t lifeTimeCount;
/* Calculate the counter value.*/
lifeTimeCount = us * pitSourceClock / 1000000U - 1U;
/* Assign to timers.*/
pit_hal_set_timer_period_count(0U, (uint32_t)lifeTimeCount);
pit_hal_set_timer_period_count(1U, (uint32_t)(lifeTimeCount >> 32U));
}
/*FUNCTION**********************************************************************
*
* Function Name : pit_read_lifetime_timer_us
* Description : Read current lifetime value in microseconds unit.
* Return an absolute time stamp in the unit of microseconds. The time stamp
* value will not exceed the timer period. Also, the timer is up-counting.
*
*END**************************************************************************/
uint64_t pit_read_lifetime_timer_us(void)
{
/* Get current lifetime timer count, and reverse it to up-counting.*/
uint64_t currentTime = (~pit_hal_read_lifetime_timer_count());
/* Convert count numbers to microseconds unit.*/
/* Note: using currentTime * 1000 rather than 1000000 to avoid short time overflow. */
return currentTime = (currentTime * 1000U) / (pitSourceClock / 1000U);
}
#endif /* FSL_FEATURE_PIT_HAS_LIFETIME_TIMER*/
/*******************************************************************************
* EOF
******************************************************************************/

View File

@ -0,0 +1,169 @@
/*
* Copyright (c) 2013 - 2014, Freescale Semiconductor, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o 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.
*
* o Neither the name of Freescale Semiconductor, Inc. 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 HOLDER 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.
*/
#include <stdlib.h>
#include <assert.h>
#include "fsl_pit_driver.h"
/*!
* @addtogroup pit_irq
* @{
*/
/*******************************************************************************
* Variables
******************************************************************************/
#if defined (KL25Z4_SERIES)
/*!
* @brief Table to save PIT IRQ enum numbers defined in CMSIS files.
*
* They are used by pit_init_channel to enable or disable PIT interrupts. This table is
* indexed by channel number which could return PIT IRQ numbers.
*/
const IRQn_Type pit_irq_ids[FSL_FEATURE_PIT_TIMER_COUNT] =
{
PIT_IRQn, PIT_IRQn
};
#elif defined (K64F12_SERIES) || defined (K70F12_SERIES) || defined (K22F51212_SERIES)
const IRQn_Type pit_irq_ids[FSL_FEATURE_PIT_TIMER_COUNT] =
{
PIT0_IRQn, PIT1_IRQn, PIT2_IRQn, PIT3_IRQn
};
#endif
/*!
* @brief Function table to save PIT isr callback function pointers.
*
* Call pit_register_isr_callback_function to install isr callback functions.
*/
pit_isr_callback_t pit_isr_callback_table[FSL_FEATURE_PIT_TIMER_COUNT] = {NULL};
/*******************************************************************************
* Code
******************************************************************************/
#if defined (KL25Z4_SERIES)
/*!
* @brief System default IRQ handler defined in startup code.
*
* Users can either edit this handler or define a callback function. Furthermore,
* interrupt manager could be used to re-map the IRQ handler to another function.
*/
void PIT_IRQHandler(void)
{
uint32_t i;
for(i=0; i < FSL_FEATURE_PIT_TIMER_COUNT; i++)
{
/* Run callback function if it exists.*/
if (pit_isr_callback_table[i])
{
(*pit_isr_callback_table[i])();
}
/* Clear interrupt flag.*/
pit_hal_clear_interrupt_flag(i);
}
}
#elif defined (K64F12_SERIES) || defined (K70F12_SERIES) || defined (K22F51212_SERIES)
void PIT0_IRQHandler(void)
{
/* Run callback function if it exists.*/
if (pit_isr_callback_table[0])
{
(*pit_isr_callback_table[0])();
}
/* Clear interrupt flag.*/
pit_hal_clear_interrupt_flag(0);
}
void PIT1_IRQHandler(void)
{
/* Run callback function if it exists.*/
if (pit_isr_callback_table[1])
{
(*pit_isr_callback_table[1])();
}
/* Clear interrupt flag.*/
pit_hal_clear_interrupt_flag(1);
}
void PIT2_IRQHandler(void)
{
/* Run callback function if it exists.*/
if (pit_isr_callback_table[2])
{
(*pit_isr_callback_table[2])();
}
/* Clear interrupt flag.*/
pit_hal_clear_interrupt_flag(2);
}
void PIT3_IRQHandler(void)
{
/* Run callback function if it exists.*/
if (pit_isr_callback_table[3])
{
(*pit_isr_callback_table[3])();
}
/* Clear interrupt flag.*/
pit_hal_clear_interrupt_flag(3);
}
#endif
/*! @} */
/*FUNCTION**********************************************************************
*
* Function Name : pit_register_isr_callback_function
* Description : Register pit isr callback function.
* System default ISR interfaces are already defined in fsl_pit_irq.c. Users
* can either edit these ISRs or use this function to register a callback
* function. The default ISR will run the callback function it there is one
* installed here.
*END**************************************************************************/
void pit_register_isr_callback_function(uint32_t timer, pit_isr_callback_t function)
{
assert(timer < FSL_FEATURE_PIT_TIMER_COUNT);
assert(function != NULL);
pit_isr_callback_table[timer] = function;
}
/*******************************************************************************
* EOF
******************************************************************************/

View File

@ -0,0 +1,3 @@
PIT_DRIVER_DIR := $(SDK_ROOT)/platform/drivers/pit
SOURCES += $(wildcard $(PIT_DRIVER_DIR)/src/*.c)
INCLUDES += $(PIT_DRIVER_DIR)

View File

@ -31,13 +31,18 @@
#define __FSL_ENET_FEATURES_H__
#if defined(CPU_MK63FN1M0VMD12) || defined(CPU_MK63FN1M0VMD12WS) || defined(CPU_MK64FN1M0VMD12) || defined(CPU_MK64FX512VMD12)
#define FSL_FEATURE_ENET_DMA_BIG_ENDIAN_ONLY (1)
#if defined(CPU_MK63FN1M0VMD12) || defined(CPU_MK63FN1M0VMD12WS)
#define FSL_FEATURE_ENET_DMA_BIG_ENDIAN_ONLY (1)
#define FSL_FEATURE_ENET_SUPPORT_PTP (0)
#define FSL_FEATURE_ENET_INTERRUPT_COUNT (4)
#define FSL_FEATURE_ENET_PTP_TIMER_CHANNEL_INTERRUPT (0)
#elif defined(CPU_MK64FN1M0VMD12) || defined(CPU_MK64FX512VMD12)
#define FSL_FEATURE_ENET_DMA_BIG_ENDIAN_ONLY (0)
#define FSL_FEATURE_ENET_SUPPORT_PTP (0)
#define FSL_FEATURE_ENET_INTERRUPT_COUNT (4)
#define FSL_FEATURE_ENET_PTP_TIMER_CHANNEL_INTERRUPT (0)
#elif defined(CPU_MK70FN1M0VMJ12)
#define FSL_FEATURE_ENET_DMA_BIG_ENDIAN_ONLY (1)
#define FSL_FEATURE_ENET_DMA_BIG_ENDIAN_ONLY (1)
#define FSL_FEATURE_ENET_SUPPORT_PTP (0)
#define FSL_FEATURE_ENET_INTERRUPT_COUNT (4)
#else

View File

@ -0,0 +1,569 @@
/*
* Copyright (c) 2013 - 2014, Freescale Semiconductor, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o 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.
*
* o Neither the name of Freescale Semiconductor, Inc. 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 HOLDER 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.
*/
#if !defined(__FSL_OS_ABSTRACTION_H__)
#define __FSL_OS_ABSTRACTION_H__
#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>
#if defined __CC_ARM
#define inline __inline
#endif
/*!
* @addtogroup os_abstraction
* @{
*/
/*! @brief Status values to be returned by functions. */
typedef enum
{
kSuccess = 0, /*!< Functions work correctly. */
kError, /*!< Functions work failed. */
kTimeout, /*!< Timeout occurs while waiting for an object. */
kIdle /*!< Can not get the object in non-blocking mode.*/
}fsl_rtos_status;
/*! @brief The event flags are set or not.*/
typedef enum
{
kFlagNotSet = 0, /*!< The flags checked are set. */
kFlagSet /*!< The flags checked are not set. */
}event_status;
/*! @brief The event flags are cleared automatically or manually.*/
typedef enum
{
kEventAutoClr = 0, /*!< The flags of the event will be cleared automatically. */
kEventManualClr /*!< The flags of the event will be cleared manually. */
}event_clear_type;
/* Include required header file based on RTOS selection */
#if defined (FSL_RTOS_MQX)
/*! @brief Macro to set message queue copy messages to internal memory or not. */
#define __FSL_RTOS_MSGQ_COPY_MSG__ 1
#include "fsl_os_abstraction_mqx.h"
#elif defined (FSL_RTOS_FREE_RTOS)
#define __FSL_RTOS_MSGQ_COPY_MSG__ 1
#include "fsl_os_abstraction_free_rtos.h"
#elif defined (FSL_RTOS_UCOSII)
#define __FSL_RTOS_MSGQ_COPY_MSG__ 1
#include "fsl_os_abstraction_ucosii.h"
#elif defined (FSL_RTOS_UCOSIII)
#define __FSL_RTOS_MSGQ_COPY_MSG__ 1
#include "fsl_os_abstraction_ucosiii.h"
#elif defined (FSL_RTOS_CMSIS)
#define __FSL_RTOS_MSGQ_COPY_MSG__ 0
#include "fsl_os_abstraction_cmsis.h"
#elif defined (FSL_RTOS_MBED)
#define __FSL_RTOS_MSGQ_COPY_MSG__ 1
#include "fsl_os_abstraction_mbed.h"
#else
#define __FSL_RTOS_MSGQ_COPY_MSG__ 1
#include "fsl_os_abstraction_bm.h"
#endif
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif
/*!
* @name Synchronization
* @{
*/
/*!
* @brief Initialize a synchronization object to a given state.
*
* @param obj The sync object to initialize.
* @param initValue The initial value the object will be set to.
*
* @retval kSuccess The object was successfully created.
* @retval kError Invalid parameter or no more objects can be created.
*/
fsl_rtos_status sync_create(sync_object_t *obj, uint8_t initValue);
/*!
* @brief Wait for the synchronization object.
*
* This function checks the sync object's counting value, if it is
* positive, decreases it and returns kSuccess, otherwise, timeout will be
* used for wait.
*
* @param obj Pointer to the synchronization object.
* @param timeout The maximum number of milliseconds to wait for the object to be signalled.
* Pass the #kSyncWaitForever constant to wait indefinitely for someone to signal the object.
* A value of 0 should not be passed to this function. Instead, use sync_poll for
* a non blocking check.
*
* @retval kSuccess The object was signalled.
* @retval kTimeout A timeout occurred.
* @retval kError An incorrect parameter was passed.
* @retval kIdle The object has not been signalled.
*
* @note There could be only one process waiting for the object at the same time.
*/
fsl_rtos_status sync_wait(sync_object_t *obj, uint32_t timeout);
/*!
* @brief Checks a synchronization object's status.
*
* This function is used to poll a sync object's status.
* If the sync object's counting value is positive, decrease it and return
* kSuccess. If the object's counting value is 0, the function will
* return kIdle immediately
*
* @param obj The synchronization object.
*
* @retval kSuccess The object was signalled.
* @retval kIdle The object was not signalled.
* @retval kError An incorrect parameter was passed.
*/
fsl_rtos_status sync_poll(sync_object_t *obj);
/*!
* @brief Signal for someone waiting on the synchronization object to wake up.
*
* This function should not be called from an ISR.
*
* @param obj The synchronization object to signal.
*
* @retval kSuccess The object was successfully signaled.
* @retval kError The object can not be signaled or invalid parameter.
*/
fsl_rtos_status sync_signal(sync_object_t *obj);
/*!
* @brief Signal for someone waiting on the synchronization object to wake up.
*
* This function should only be called from an ISR.
*
* @param obj The synchronization object to signal.
*
* @retval kSuccess The object was successfully signaled.
* @retval kError The object can not be signaled or invalid parameter.
*/
fsl_rtos_status sync_signal_from_isr(sync_object_t *obj);
/*!
* @brief Destroy a previously created synchronization object.
*
* @param obj The synchronization object to destroy.
*
* @retval kSuccess The object was successfully destroyed.
* @retval kError Object destruction failed.
*/
fsl_rtos_status sync_destroy(sync_object_t *obj);
/* @} */
/*!
* @name Resource locking
* @{
*/
/*!
* @brief Initialize a locking object.
*
* @param obj The lock object to initialize.
*
* @retval kSuccess The lock is created successfully.
* @retval kError Tke lock creation failed.
*/
fsl_rtos_status lock_create(lock_object_t *obj);
/*!
* @brief Wait for the object to be unlocked and lock it.
*
* This function will wait for some time or wait forever if could not get the lock.
*
* @param obj The locking object.
* @param timeout The maximum number of milliseconds to wait for the mutex.
* Pass the #kSyncWaitForever constant to wait indefinitely for someone to unlock the object.
* A value of 0 should not be passed to this function. Instead, use lock_poll for a non
* blocking check.
*
* @retval kSuccess The lock was obtained.
* @retval kTimeout A timeout occurred.
* @retval kError An incorrect parameter was passed.
*/
fsl_rtos_status lock_wait(lock_object_t *obj, uint32_t timeout);
/*!
* @brief Checks if a locking object can be locked and locks it if possible.
*
* This function returns instantly if could not get the lock.
*
* @param obj The locking object.
*
* @retval kSuccess The lock was obtained.
* @retval kIdle The lock could not be obtained.
* @retval kError An incorrect parameter was passed.
*
* @note There could be only one process waiting for the object at the same time.
* For RTOSes, wait for a lock recursively by one task is not supported.
*
*/
fsl_rtos_status lock_poll(lock_object_t *obj);
/*!
* @brief Unlock a previously locked object.
*
* @param obj The locking object to unlock.
*
* @retval kSuccess The object was successfully unlocked.
* @retval kError The object can not be unlocked or invalid parameter.
*/
fsl_rtos_status lock_release(lock_object_t *obj);
/*!
* @brief Destroy a previously created locking object.
*
* @param obj The locking object to destroy.
*
* @retval kSuccess The object was successfully destroyed.
* @retval kError Object destruction failed.
*/
fsl_rtos_status lock_destroy(lock_object_t *obj);
/* @} */
/*!
* @name Event signaling
* @{
*/
/*!
* @brief Initializes the event object.
*
* When the object is created, the flags is 0.
*
* @param obj Pointer to the event object to initialize.
* @param clearType The event is auto-clear or manual-clear.
*
* @retval kSuccess The object was successfully created.
* @retval kError Incorrect parameter or no more objects can be created.
*/
fsl_rtos_status event_create(event_object_t *obj, event_clear_type clearType);
/*!
* @brief Wait for any event flags to be set.
*
* This function will wait for some time or wait forever if no flags are set. Any flags set
* will wake up the function.
*
* @param obj The event object.
* @param timeout The maximum number of milliseconds to wait for the event.
* Pass the #kSyncWaitForever constant to wait indefinitely. A value of 0 should not be passed
* to this function.
* @param setFlags Pointer to receive the flags that were set.
*
* @retval kSuccess An event was set.
* @retval kTimeout A timeout occurred.
* @retval kError An incorrect parameter was passed.
*/
fsl_rtos_status event_wait(event_object_t *obj, uint32_t timeout, event_group_t *setFlags);
/*!
* @brief Set one or more event flags of an event object.
*
* This function should not be called from an ISR.
*
* @param obj The event object.
* @param flags Event flags to be set.
*
* @retval kSuccess The flags were successfully set.
* @retval kError An incorrect parameter was passed.
*
* @note There could be only one process waiting for the event.
*
*/
fsl_rtos_status event_set(event_object_t *obj, event_group_t flags);
/*!
* @brief Set one or more event flags of an event object.
*
* This function should only be called from an ISR.
*
* @param obj The event object.
* @param flags Event flags to be set.
*
* @retval kSuccess The flags were successfully set.
* @retval kError An incorrect parameter was passed.
*/
fsl_rtos_status event_set_from_isr(event_object_t *obj, event_group_t flags);
/*!
* @brief Clear one or more events of an event object.
*
* This function should not be called from an ISR.
*
* @param obj The event object.
* @param flags Event flags to be clear.
*
* @retval kSuccess The flags were successfully cleared.
* @retval kError An incorrect parameter was passed.
*/
fsl_rtos_status event_clear(event_object_t *obj, event_group_t flags);
/*!
* @brief Check the flags are set or not.
*
* @param obj The event object.
* @param flag The flag to check.
*
* @retval kFlagsSet The flags checked are set.
* @retval kFlagsNotSet The flags checked are not set or got an error.
*/
event_status event_check_flags(event_object_t *obj, event_group_t flag);
/*!
* @brief Destroy a previously created event object.
*
* @param obj The event object to destroy.
*
* @retval kSuccess The object was successfully destroyed.
* @retval kError Event destruction failed.
*/
fsl_rtos_status event_destroy(event_object_t *obj);
/* @} */
/*!
* @name Thread management
* @{
*/
/*!
* @brief Create a task.
*
* This function is wrapped by the macro task_create. Generally, this function is for
* internal use only, applications must use FSL_RTOS_TASK_DEFINE to define resources for
* task statically then use task_create to create task. If applications have prepare
* the resouces for task dynamically, they can use this function to create the task.
*
* @param task The task function.
* @param name The name of this task.
* @param stackSize The stack size in byte.
* @param stackMem Pointer to the stack. For bare metal, MQX and FreeRTOS, this could be NULL.
* @param priority Initial priority of the task.
* @param param Pointer to be passed to the task when it is created.
* @param usesFloat This task will use float register or not.
* @param handler Pointer to the task handler.
*
* @retval kSuccess The task was successfully created.
* @retval kError The task could not be created.
*
* @note Different tasks can not use the same task function.
*/
fsl_rtos_status __task_create(task_t task, uint8_t *name, uint16_t stackSize,
task_stack_t *stackMem, uint16_t priority,
void *param, bool usesFloat, task_handler_t *handler);
/*!
* @brief Destroy a previously created task.
* @note Depending on the RTOS, task resources may or may not be automatically freed,
* and this function may not return if the current task is destroyed.
*
* @param handler The handler of the task to destroy. Returned by the task_create function.
*
* @retval kSuccess The task was successfully destroyed.
* @retval kError Task destruction failed or invalid parameter.
*/
fsl_rtos_status task_destroy(task_handler_t handler);
/* @} */
/*!
* @name Message queues
* @{
*/
/*!
* @brief Initialize the message queue.
*
* This function will initialize the message queue that declared previously.
* Here is an example demonstrating how to use:
@code
msg_queue_handler_t handler;
MSG_QUEUE_DECLARE(my_message, msg_num, msg_size);
handler = msg_queue_create(&my_message, msg_num, msg_size);
@endcode
*
* @param queue The queue declared through the MSG_QUEUE_DECLARE macro.
* @param number The number of elements in the queue.
* @param size Size of every elements in words.
*
* @retval Handler to access the queue for put and get operations. If message queue
* created failed, return 0.
*/
msg_queue_handler_t msg_queue_create(msg_queue_t *queue, uint16_t number, uint16_t size);
/*!
* @brief Introduce an element at the tail of the queue.
*
* @param handler Queue handler returned by the msg_queue_create function.
* @param item Pointer to the element to be introduced in the queue.
*
* @retval kSuccess Element successfully introduced in the queue.
* @retval kError The queue was full or an invalid parameter was passed.
*/
fsl_rtos_status msg_queue_put(msg_queue_handler_t handler, msg_queue_item_t item);
/*!
* @brief Read and remove an element at the head of the queue.
*
* @param handler Queue handler returned by the msg_queue_create function.
* @param item Pointer to store a pointer to the element of the queue.
* @param timeout In case the queue is empty, the number of milliseconds to
* wait for an element to be introduced into the queue. Use 0 to return
* immediately or #kSyncWaitForever to wait indefinitely.
*
* @retval kSuccess Element successfully obtained from the queue.
* @retval kTimeout If a timeout was specified, the queue remained empty after timeout.
* @retval kError The queue was empty or the handler was invalid.
* @retval kIdle The queue was empty and the timeout has not expired.
*
* @note There should be only one process waiting on the queue.
*/
fsl_rtos_status msg_queue_get(msg_queue_handler_t handler,
msg_queue_item_t *item,
uint32_t timeout);
/*!
* @brief Discards all elements in the queue and leaves the queue empty.
*
* @param handler Queue handler returned by the msg_queue_create function.
*
* @retval kSuccess Queue successfully emptied.
* @retval kError Emptying queue failed.
*/
fsl_rtos_status msg_queue_flush(msg_queue_handler_t handler);
/*!
* @brief Destroy a previously created queue.
*
* @param handler Queue handler returned by the msg_queue_create function.
*
* @retval kSuccess The queue was successfully destroyed.
* @retval kError Message queue destruction failed.
*/
fsl_rtos_status msg_queue_destroy(msg_queue_handler_t handler);
/* @} */
#ifndef FSL_RTOS_MBED
/*!
* @name Memory Management
* @{
*/
/*!
* @brief Reserves the requested amount of memory in bytes.
*
* @param size Amount of bytes to reserve.
*
* @retval Pointer to the reserved memory. NULL if memory could not be allocated.
*/
void * mem_allocate(size_t size);
/*!
* @brief Reserves the requested amount of memory in bytes and initializes it to 0.
*
* @param size Amount of bytes to reserve.
*
* @retval Pointer to the reserved memory. NULL if memory could not be allocated.
*/
void * mem_allocate_zero(size_t size);
/*!
* @brief Releases the memory previously reserved.
*
* @param ptr Pointer to the start of the memory block previously reserved.
*
* @retval kSuccess Memory correctly released.
*/
fsl_rtos_status mem_free(void *ptr);
#endif
/* @} */
/*!
* @name Time management
* @{
*/
/*!
* @brief Delays execution for a number of milliseconds.
*
* @param delay The time in milliseconds to wait.
*/
void time_delay(uint32_t delay);
/* @} */
/*!
* @name Interrupt management
* @{
*/
/*!
* @brief Install interrupt handler.
*
* @param irqNumber IRQ number of the interrupt.
* @param handler The interrupt handler to install.
*
* @retval kSuccess Handler is installed successfully.
* @retval kSuccess Handler could not be installed.
*/
fsl_rtos_status interrupt_handler_register(int32_t irqNumber, void (*handler)(void));
/* @} */
#if defined(__cplusplus)
}
#endif
/*! @}*/
#endif /* __FSL_OS_ABSTRACTION_H__ */
/*******************************************************************************
* EOF
******************************************************************************/

View File

@ -0,0 +1,38 @@
/* fsl_os_mbed_abstraction.h */
/* Copyright (C) 2012 mbed.org, MIT License
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
* and associated documentation files (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge, publish, distribute,
* sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or
* substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef FSL_OS_ABSTRACTION_MBED_H_
#define FSL_OS_ABSTRACTION_MBED_H_
// This is not really an "abstraction", but rather a set of quick&dirty
// defines to allow the KSDK to compile. Currently, this is relevant only
// in the context of the ENET driver (fsl_enet_driver.c)
typedef int event_object_t;
typedef int lock_object_t;
typedef void sync_object_t;
typedef unsigned int event_group_t;
typedef int task_t;
typedef void task_stack_t;
typedef int task_handler_t;
typedef int msg_queue_handler_t;
typedef void msg_queue_t;
typedef int msg_queue_item_t;
#endif // #ifdef FSL_OS_ABSTRACTION_MBED_H_

View File

@ -0,0 +1,35 @@
/* fsl_os_mbed_abstraction.h */
/* Copyright (C) 2012 mbed.org, MIT License
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
* and associated documentation files (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge, publish, distribute,
* sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or
* substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "fsl_os_abstraction.h"
#include "wait_api.h"
fsl_rtos_status lock_destroy(lock_object_t *obj) {
return kSuccess;
}
fsl_rtos_status event_set(event_object_t *obj, event_group_t flags) {
return kSuccess;
}
void time_delay(uint32_t delay) {
wait_ms(delay);
}

View File

@ -0,0 +1,311 @@
/*
* Copyright (c) 2013 - 2014, Freescale Semiconductor, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o 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.
*
* o Neither the name of Freescale Semiconductor, Inc. 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 HOLDER 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.
*/
/*************************************************************************************************
* Includes Section
************************************************************************************************/
#include "sw_timer.h"
#include "fsl_interrupt_manager.h"
#include "fsl_clock_manager.h"
#include "fsl_pit_driver.h"
/*************************************************************************************************
* Defines & Macros Section
************************************************************************************************/
#ifndef SW_TIMER_NUMBER_CHANNELS
/*! Number of channels to be used as timers. The maximum value of channels supported is 32.*/
#define SW_TIMER_NUMBER_CHANNELS (32)
/*! Defines the count unit in ms of the software timer.*/
#define SW_TIMER_COUNT_UNIT_MS (1)
#endif
/*! Return if the timer channel is reserved.*/
#define IS_TIMER_CHANNEL_RESERVED(chann) (gs_areChannelsEnabled & (channel_enabler_t)(1 << chann))
/*************************************************************************************************
* Typedef Section
************************************************************************************************/
#if (SW_TIMER_NUMBER_CHANNELS <= 8)
/*! Defines the size of variable that stores "enable" flags of each channel.*/
typedef uint8_t channel_enabler_t;
#else
#if (SW_TIMER_NUMBER_CHANNELS <= 16)
/*! Defines the size of variable that stores "enable" flags of each channel.*/
typedef uint16_t channel_enabler_t;
#else
#if (SW_TIMER_NUMBER_CHANNELS <= 32)
/*! Defines the size of variable that stores "enable" flags of each channel.*/
typedef uint32_t channel_enabler_t;
#else
#error "Cannot handle more than 32 auxiliary software timer channels."
#endif
#endif
#endif
/*************************************************************************************************
* Global Constants Section
************************************************************************************************/
/*************************************************************************************************
* Static Constants Section
************************************************************************************************/
/** Constant to select the PIT timer channel to use for timebase. Channels 0 and 1 have special
* hardware trigger capabilities, so they should be avoided.
*/
static const uint8_t kSWTimerPITChannel = FSL_FEATURE_PIT_TIMER_COUNT - 1;
/*************************************************************************************************
* Global Variables Section
************************************************************************************************/
/*************************************************************************************************
* Static Variables Section
************************************************************************************************/
/*! Free running counter that everyone can read.*/
static volatile time_free_counter_t gs_freeCounter;
/*! Independent counters of software timer module. A counter is defined for every channel.*/
static volatile time_counter_t gs_channelCounters[SW_TIMER_NUMBER_CHANNELS];
/*! Variable used to indicate which channels are enabled. Bit 0 corresponds to channel 0, bit 1 to*/
/*! channel 1, etc.*/
static volatile channel_enabler_t gs_areChannelsEnabled;
/*************************************************************************************************
* Functions Section
************************************************************************************************/
/* See sw_timer.h for documentation of this function.*/
uint32_t sw_timer_init_service(void)
{
pit_user_config_t pitConfig;
/* All channels are disabled*/
gs_areChannelsEnabled = 0;
/* Init free running counter*/
gs_freeCounter = 0;
/* Define PIT channel init structure. */
pitConfig.isInterruptEnabled = true;
pitConfig.isTimerChained = false;
pitConfig.periodUs = 1000;/* Set 1ms period */
/* Init PIT module and enable all timers run in debug mode.*/
pit_init_module(true);
/* Init PIT channel. */
pit_init_channel(kSWTimerPITChannel, &pitConfig);
/* Register PIT callback function.*/
pit_register_isr_callback_function(kSWTimerPITChannel, sw_timer_update_counters);
/* Start timer counting. */
pit_timer_start(kSWTimerPITChannel);
return kSwTimerStatusSuccess;
}
/* See sw_timer.h for documentation of this function.*/
void sw_timer_shutdown_service(void)
{
pit_shutdown();
}
/* See sw_timer.h for documentation of this function.*/
uint8_t sw_timer_reserve_channel(void)
{
static uint8_t lastFreeChannel = 0;
uint8_t searchIndex;
uint8_t newReservedChannel;
/* Initialize search index with the last free channel to search faster for a free channel*/
searchIndex = lastFreeChannel;
/* Not channel available by default*/
newReservedChannel = kSwTimerChannelNotAvailable;
/* Searching for a free channel*/
do {
/* The channel is free*/
if(!IS_TIMER_CHANNEL_RESERVED(searchIndex))
{
/* Set channel as reserved*/
newReservedChannel = searchIndex;
gs_areChannelsEnabled |= (1u << newReservedChannel);
/* Update last free channel with the next channel*/
lastFreeChannel = newReservedChannel + 1;
/* Flag of the last channel has been checked and need to start over with channel 0*/
if (lastFreeChannel == SW_TIMER_NUMBER_CHANNELS)
{
lastFreeChannel = 0;
}
}
/* The channel is already reserved*/
else
{
searchIndex = (searchIndex + 1) % SW_TIMER_NUMBER_CHANNELS;
}
}while((searchIndex != lastFreeChannel) &&
(kSwTimerChannelNotAvailable == newReservedChannel));
return newReservedChannel;
}
/* See sw_timer.h for documentation of this function.*/
sw_timer_channel_status_t sw_timer_get_channel_status(uint8_t timerChannel)
{
sw_timer_channel_status_t channelStatus;
/* Is it a valid channel?*/
if(SW_TIMER_NUMBER_CHANNELS > timerChannel)
{
/* The channel is reserved*/
if(IS_TIMER_CHANNEL_RESERVED(timerChannel))
{
/* The timeout has expired*/
if(0 >= gs_channelCounters[timerChannel])
{
channelStatus = kSwTimerChannelExpired;
}
/* The counter is still counting*/
else
{
channelStatus = kSwTimerChannelStillCounting;
}
}
/* The channel is not reserved*/
else
{
channelStatus = kSwTimerChannelIsDisable;
}
}
/* The channel is not valid*/
else
{
channelStatus = kSwTimerChannelNotAvailable;
}
return channelStatus;
}
/* See sw_timer.h for documentation of this function.*/
uint32_t sw_timer_start_channel(uint8_t timerChannel, time_counter_t timeout)
{
uint32_t startStatus;
/* Is it a valid channel?*/
if(SW_TIMER_NUMBER_CHANNELS > timerChannel)
{
/* Set the given timeout in the corresponding channel counter. The timeout should be a */
/* multiple of SW_TIMER_COUNT_UNIT_MS, otherwise it will be taken the integer part of the */
/* division.*/
gs_channelCounters[timerChannel] = timeout / SW_TIMER_COUNT_UNIT_MS;
startStatus = kSwTimerStatusSuccess;
}
else
{
startStatus = kSwTimerStatusInvalidChannel;
}
return startStatus;
}
/* See sw_timer.h for documentation of this function.*/
uint32_t sw_timer_release_channel(uint8_t timerChannel)
{
uint32_t releaseStatus;
/* Is it a valid channel?*/
if(SW_TIMER_NUMBER_CHANNELS > timerChannel)
{
/* Set channel as disable*/
gs_areChannelsEnabled &= (~(1u << timerChannel));
releaseStatus = kSwTimerStatusSuccess;
}
else
{
releaseStatus = kSwTimerStatusInvalidChannel;
}
return releaseStatus;
}
/* See sw_timer.h for documentation of this function.*/
time_free_counter_t sw_timer_get_free_counter(void)
{
return gs_freeCounter;
}
/* See sw_timer.h for documentation of this function.*/
void sw_timer_update_counters(void)
{
uint8_t index;
index = SW_TIMER_NUMBER_CHANNELS;
do {
--index;
/* Decrement all counters. To determine if the timeout has expired call */
--gs_channelCounters[index];
} while(0 != index);
/* Increment free running counter*/
++gs_freeCounter;
}
/*******************************************************************************
* EOF
******************************************************************************/

View File

@ -0,0 +1,191 @@
/*
* Copyright (c) 2013 - 2014, Freescale Semiconductor, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o 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.
*
* o Neither the name of Freescale Semiconductor, Inc. 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 HOLDER 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.
*/
#if !defined(__SW_TIMER_H__)
#define __SW_TIMER_H__
#include <stdint.h>
#include <stdbool.h>
/*! @addtogroup sw_timer Software Timer
* @brief This module is used to interface with Abstract Timer HAL to generate periodical timeouts
* required through different modules of the AOA protocol. This block will be based on 1ms
* ticks for all the timeout calculations. The HAL Interface block used to communicate with
* this must have the same 1ms timeout configured. This module can generate different
* software timer channels based on the same 1ms.
*/
/*! @{*/
/*! Definition of the possible status of a software channel timer. */
typedef enum SwTimerChannelStatus
{
kSwTimerChannelExpired = 0x00, /*!< Indicates the timer channel has counted the given ms*/
kSwTimerChannelStillCounting = 0x01, /*!< Indicates the timeout of the channel has not expired
and the timer is still counting.*/
kSwTimerChannelIsDisable = 0x02, /*!< Indicates the timer channel is not reserved. */
kSwTimerChannelNotAvailable = 0xFF /*!< Indicates there are not available channels to reserve
or the requested channel is not available.*/
}sw_timer_channel_status_t;
/*! List of status and errors. */
enum _sw_timer_errors
{
kSwTimerStatusSuccess, /*!< The execution was successful.*/
kSwTimerStatusFail, /*!< The execution failed.*/
kSwTimerStatusInvalidChannel /*!< The given channel is not valid. Valid channels are 0 to
(SW_TIMER_NUMBER_CHANNELS - 1). */
};
/*!
* Data type of the counter of each timer channel. If it is an int8_t the counter will count
* up to 127ms, int16_t up to 32767ms and int32_t up to 2147483647ms.
*/
typedef int32_t time_counter_t;
/*! Max timeout value according to size of the time counter */
enum sw_timer_timeouts
{
kSwTimerMaxTimeout = 2147483647
};
/*!
* Data type of the free running counter. This data type should be unsigned and will count up to
* 255ms if it is uint8_t, 65535ms for uint16_t and 4294967295ms for uint32_t.
*/
typedef uint32_t time_free_counter_t;
#if defined(__cplusplus)
extern "C" {
#endif /* __cplusplus*/
/*!
* @brief Initializes the software timer module. Prepares variables and HAL layer to provide timer
* services. Starts the free running counter which will be available to get its value any
* time while the service is running; it is useful whenever a module wants to keep track of
* time, but do not wants to reserve a channel.
*
* @return status_t Returns software timer status after initialization.
* @retval kSwTimerStatusSuccess The initialization was successful and the software timer is ready
* to provide services.
* @retval kSwTimerStatusFail The initialization failed.
*/
uint32_t sw_timer_init_service(void);
/*!
* @brief Deinitializes the software timer module. Shutdown HAL layer, so no timer service can be
* provided after the execution of this function.
*
* @return void
*/
void sw_timer_shutdown_service(void);
/*!
* @brief Reserves a free timer channel to be used by any module and returns its identifier.
*
* @return uint8_t Returns the number of the channel that was reserved.
* @retval Any value between 0 and SW_TIMER_NUMBER_CHANNELS is a valid channel. It indicates the
* channel was reserved and can be used.
* @retval kSwTimerChannelNotAvailable If there is not any available channel, because all
* channels are already reserved.
*/
uint8_t sw_timer_reserve_channel(void);
/*!
* @brief Returns the actual status of the given timer channel. The timer has to be previously
* started to return a valid status.
*
* @param timerChannel [in] Indicates the timer channel which status is going to be returned.
*
* @return sw_timer_channel_status_t Current status of the given timer channel.
* @retval kSwTimerChannelExpired Indicates the timer channel has counted the given ms.
* @retval kSwTimerChannelStillCounting Indicates the timeout of the channel has not expired and
the timer is still counting.
* @retval kSwTimerChannelIsDisable Indicates the timer channel is not reserved.
* @retval kSwTimerChannelNotAvailable Indicates the timer channel is invalid.
*/
sw_timer_channel_status_t sw_timer_get_channel_status(uint8_t timerChannel);
/*!
* @brief Starts the count down of the given timer channel. The timer channel has to be previously
* reserved.
*
* @param timerChannel [in] Indicates the timer channel that is going to be started.
* @param timeout [in] Time in ms that the timer channel will count. The timeout should be
a multiple of count unit of the timer, otherwise it will be taken
the integer part of the division and the exact count will not be
achieved
*
* @return status_t Reports failures in the execution of the function.
* @retval kSwTimerStatusSuccess A channel was started successfully.
* @retval kSwTimerStatusInvalidChannel The timer channel is invalid, it does not exist.
*/
uint32_t sw_timer_start_channel(uint8_t timerChannel, time_counter_t timeout);
/*!
* @brief Releases the given timer channel, so it can be used by someone else.
*
* @param timerChannel [in] Identifier of the timer channel.
*
* @return status_t Reports failures in the execution of the function.
* @retval kSwTimerStatusSuccess A channel was released successfully.
* @retval kSwTimerStatusInvalidChannel The timer channel is invalid, it does not exist.
*/
uint32_t sw_timer_release_channel(uint8_t timerChannel);
/*!
* @brief Gets the current value of the free running counter. Any module can keep track of the time
* by reading this counter and calculates time difference. No reservation of timer channel
* is needed. Consider for calculations that when the counter overflows it will start from
* 0 again.
*
* @return time_free_counter_t Returns current count of the free running counter.
*/
time_free_counter_t sw_timer_get_free_counter(void);
/*!
* @brief This function is called every 1ms by the interruption and update count down values of all
* timer channels.
*
* @return void
*/
void sw_timer_update_counters(void);
#if defined(__cplusplus)
}
#endif /* __cplusplus*/
/*! @}*/
/*Group sw_timer*/
#endif /* __SW_TIMER_H__ */
/*******************************************************************************
* EOF
******************************************************************************/

View File

@ -22,14 +22,13 @@
#include "lwip/netif.h"
#include "netif/etharp.h"
#include "lwip/dhcp.h"
#include "arch/lpc17_emac.h"
#include "lpc_phy.h"
#include "eth_arch.h"
#include "lwip/tcpip.h"
#include "mbed.h"
/* TCP/IP and Network Interface Initialisation */
static struct netif lpcNetif;
static struct netif netif;
static char mac_addr[19];
static char ip_addr[17] = "\0";
@ -64,12 +63,12 @@ static void init_netif(ip_addr_t *ipaddr, ip_addr_t *netmask, ip_addr_t *gw) {
tcpip_init(tcpip_init_done, NULL);
tcpip_inited.wait();
memset((void*) &lpcNetif, 0, sizeof(lpcNetif));
netif_add(&lpcNetif, ipaddr, netmask, gw, NULL, lpc_enetif_init, tcpip_input);
netif_set_default(&lpcNetif);
memset((void*) &netif, 0, sizeof(netif));
netif_add(&netif, ipaddr, netmask, gw, NULL, eth_arch_enetif_init, tcpip_input);
netif_set_default(&netif);
netif_set_link_callback (&lpcNetif, netif_link_callback);
netif_set_status_callback(&lpcNetif, netif_status_callback);
netif_set_link_callback (&netif, netif_link_callback);
netif_set_status_callback(&netif, netif_status_callback);
}
static void set_mac_address(void) {
@ -106,18 +105,17 @@ int EthernetInterface::init(const char* ip, const char* mask, const char* gatewa
}
int EthernetInterface::connect(unsigned int timeout_ms) {
NVIC_SetPriority(ENET_IRQn, ((0x01 << 3) | 0x01));
NVIC_EnableIRQ(ENET_IRQn);
eth_arch_enable_interrupts();
int inited;
if (use_dhcp) {
dhcp_start(&lpcNetif);
dhcp_start(&netif);
// Wait for an IP Address
// -1: error, 0: timeout
inited = netif_up.wait(timeout_ms);
} else {
netif_set_up(&lpcNetif);
netif_set_up(&netif);
// Wait for the link up
inited = netif_linked.wait(timeout_ms);
@ -128,13 +126,13 @@ int EthernetInterface::connect(unsigned int timeout_ms) {
int EthernetInterface::disconnect() {
if (use_dhcp) {
dhcp_release(&lpcNetif);
dhcp_stop(&lpcNetif);
dhcp_release(&netif);
dhcp_stop(&netif);
} else {
netif_set_down(&lpcNetif);
netif_set_down(&netif);
}
NVIC_DisableIRQ(ENET_IRQn);
eth_arch_disable_interrupts();
return 0;
}

View File

@ -20,8 +20,8 @@
#ifndef ETHERNETINTERFACE_H_
#define ETHERNETINTERFACE_H_
#if !defined(TARGET_LPC1768) && !defined(TARGET_LPC4088)
#error The Ethernet Interface library is supported only on the mbed NXP LPC1768
#if !defined(TARGET_LPC1768) && !defined(TARGET_LPC4088) && !defined(TARGET_K64F)
#error The Ethernet Interface library is not supported on this target
#endif
#include "rtos.h"

View File

@ -0,0 +1,41 @@
/* EthernetInterface.h */
/* Copyright (C) 2012 mbed.org, MIT License
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
* and associated documentation files (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge, publish, distribute,
* sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or
* substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
// Architecture specific Ethernet interface
// Must be implemented by each target
#ifndef ETHARCH_H_
#define ETHARCH_H_
#include "lwip/netif.h"
#ifdef __cplusplus
extern "C" {
#endif
void eth_arch_enable_interrupts(void);
void eth_arch_disable_interrupts(void);
err_t eth_arch_enetif_init(struct netif *netif);
#ifdef __cplusplus
}
#endif
#endif // #ifndef ETHARCHINTERFACE_H_

View File

@ -0,0 +1,455 @@
/*
* Copyright (c) 2013 - 2014, Freescale Semiconductor, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o 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.
*
* o Neither the name of Freescale Semiconductor, Inc. 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 HOLDER 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.
*/
/* Modified by mbed for the lwIP port */
#include "fsl_enet_driver.h"
#include "fsl_enet_hal.h"
#include "fsl_clock_manager.h"
#include "fsl_interrupt_manager.h"
#include <string.h>
#include "sys_arch.h"
/*******************************************************************************
* Variables
******************************************************************************/
/*! @brief Define ENET's IRQ list */
void *enetIfHandle;
/*! @brief Define MAC driver API structure and for application of stack adaptor layer*/
const enet_mac_api_t g_enetMacApi =
{
enet_mac_init,
NULL, // enet_mac_deinit,
NULL, // enet_mac_send,
#if !ENET_RECEIVE_ALL_INTERRUPT
NULL, // enet_mac_receive,
#endif
enet_mii_read,
enet_mii_write,
NULL, // enet_mac_add_multicast_group,
NULL, //enet_mac_leave_multicast_group,
};
/*******************************************************************************
* Code
******************************************************************************/
// NOTE: we need these functions to be non-blocking fpr the PHY task, hence the
// osDelay() below
/*FUNCTION****************************************************************
*
* Function Name: enet_mii_read
* Return Value: The execution status.
* Description: Read function.
* This interface read data over the (R)MII bus from the specified PHY register,
* This function is called by all PHY interfaces.
*END*********************************************************************/
uint32_t enet_mii_read(uint32_t instance, uint32_t phyAddr, uint32_t phyReg, uint32_t *dataPtr)
{
uint32_t counter;
/* Check the input parameters*/
if (!dataPtr)
{
return kStatus_ENET_InvalidInput;
}
/* Check if the mii is enabled*/
if (!enet_hal_is_mii_enabled(instance))
{
return kStatus_ENET_Miiuninitialized;
}
/* Clear the MII interrupt event*/
enet_hal_clear_interrupt(instance, kEnetMiiInterrupt);
/* Read command operation*/
enet_hal_set_mii_command(instance, phyAddr, phyReg, kEnetReadValidFrame, 0);
/* Poll for MII complete*/
for (counter = 0; counter < kEnetMaxTimeout; counter++)
{
if (enet_hal_get_interrupt_status(instance, kEnetMiiInterrupt))
{
break;
}
osDelay(1);
}
/* Check for timeout*/
if (counter == kEnetMaxTimeout)
{
return kStatus_ENET_TimeOut;
}
/* Get data from mii register*/
*dataPtr = enet_hal_get_mii_data(instance);
/* Clear MII interrupt event*/
enet_hal_clear_interrupt(instance, kEnetMiiInterrupt);
return kStatus_ENET_Success;
}
/*FUNCTION****************************************************************
*
* Function Name: enet_mii_write
* Return Value: The execution status.
* Description: Write function.
* This interface write data over the (R)MII bus to the specified PHY register.
* This function is called by all PHY interfaces.
*END*********************************************************************/
uint32_t enet_mii_write(uint32_t instance, uint32_t phyAddr, uint32_t phyReg, uint32_t data)
{
uint32_t counter;
/* Check if the mii is enabled*/
if (!enet_hal_is_mii_enabled(instance))
{
return kStatus_ENET_Miiuninitialized;
}
/* Clear the MII interrupt event*/
enet_hal_clear_interrupt(instance, kEnetMiiInterrupt);
/* Read command operation*/
enet_hal_set_mii_command(instance, phyAddr, phyReg, kEnetWriteValidFrame, data);
/* Poll for MII complete*/
for (counter = 0; counter < kEnetMaxTimeout; counter++)
{
if (enet_hal_get_interrupt_status(instance, kEnetMiiInterrupt))
{
break;
}
osDelay(1);
}
/* Check for timeout*/
if (counter == kEnetMaxTimeout)
{
return kStatus_ENET_TimeOut;
}
/* Clear MII intrrupt event*/
enet_hal_clear_interrupt(instance, kEnetMiiInterrupt);
return kStatus_ENET_Success;
}
/*FUNCTION****************************************************************
*
* Function Name: enet_mac_mii_init
* Return Value: The execution status.
* Description:Initialize the ENET Mac mii(mdc/mdio)interface.
*END*********************************************************************/
uint32_t enet_mac_mii_init(enet_dev_if_t * enetIfPtr)
{
uint32_t frequency;
/* Check the input parameters*/
if (enetIfPtr == NULL)
{
return kStatus_ENET_InvalidInput;
}
/* Configure mii speed*/
clock_manager_get_frequency(kSystemClock, &frequency);
enet_hal_config_mii(enetIfPtr->deviceNumber, (frequency/(2 * enetIfPtr->macCfgPtr->miiClock) + 1),
kEnetMdioHoldOneClkCycle, false);
return kStatus_ENET_Success;
}
/*FUNCTION****************************************************************
*
* Function Name: enet_mac_rxbd_init
* Return Value: The execution status.
* Description:Initialize the ENET receive buffer descriptors.
* Note: If you do receive on receive interrupt handler the receive
* data buffer number can be the same as the receive descriptor numbers.
* But if you are polling receive frames please make sure the receive data
* buffers are more than buffer descriptors to guarantee a good performance.
*END*********************************************************************/
uint32_t enet_mac_rxbd_init(enet_dev_if_t * enetIfPtr, enet_rxbd_config_t *rxbdCfg)
{
/* Check the input parameters*/
if ((!enetIfPtr) || (!rxbdCfg))
{
return kStatus_ENET_InvalidInput;
}
enetIfPtr->macContextPtr->bufferdescSize = enet_hal_get_bd_size();
/* Initialize the bd status*/
enetIfPtr->macContextPtr->isRxFull = false;
/* Initialize receive bd base address and current address*/
enetIfPtr->macContextPtr->rxBdBasePtr = rxbdCfg->rxBdPtrAlign;
enetIfPtr->macContextPtr->rxBdCurPtr = enetIfPtr->macContextPtr->rxBdBasePtr;
enetIfPtr->macContextPtr->rxBdDirtyPtr = enetIfPtr->macContextPtr->rxBdBasePtr;
enet_hal_set_rxbd_address(enetIfPtr->deviceNumber, (uint32_t)(enetIfPtr->macContextPtr->rxBdBasePtr));
return kStatus_ENET_Success;
}
/*FUNCTION****************************************************************
*
* Function Name: enet_mac_txbd_init
* Return Value: The execution status.
* Description:Initialize the ENET transmit buffer descriptors.
* This function prepare all of the transmit buffer descriptors.
*END*********************************************************************/
uint32_t enet_mac_txbd_init(enet_dev_if_t * enetIfPtr, enet_txbd_config_t *txbdCfg)
{
/* Check the input parameters*/
if ((!enetIfPtr) || (!txbdCfg))
{
return kStatus_ENET_InvalidInput;
}
/* Initialize the bd status*/
enetIfPtr->macContextPtr->isTxFull = false;
/* Initialize transmit bd base address and current address*/
enetIfPtr->macContextPtr->txBdBasePtr = txbdCfg->txBdPtrAlign;
enetIfPtr->macContextPtr->txBdCurPtr = enetIfPtr->macContextPtr->txBdBasePtr;
enetIfPtr->macContextPtr->txBdDirtyPtr = enetIfPtr->macContextPtr->txBdBasePtr;
enet_hal_set_txbd_address(enetIfPtr->deviceNumber, (uint32_t)(enetIfPtr->macContextPtr->txBdBasePtr));
return kStatus_ENET_Success;
}
/*FUNCTION****************************************************************
*
* Function Name: enet_mac_configure_fifo_accel
* Return Value: The execution status.
* Description: Configure the ENET FIFO and Accelerator.
*END*********************************************************************/
uint32_t enet_mac_configure_fifo_accel(enet_dev_if_t * enetIfPtr)
{
enet_config_rx_fifo_t rxFifo;
enet_config_tx_fifo_t txFifo;
/* Check the input parameters*/
if (!enetIfPtr)
{
return kStatus_ENET_InvalidInput;
}
/* Configure tx/rx accelerator*/
if (enetIfPtr->macCfgPtr->isRxAccelEnabled)
{
enet_hal_config_rx_accelerator(enetIfPtr->deviceNumber,
(enet_config_rx_accelerator_t *)&(enetIfPtr->macCfgPtr->rxAcceler));
if ((enetIfPtr->macCfgPtr->rxAcceler.isIpcheckEnabled) || (enetIfPtr->macCfgPtr->rxAcceler.isProtocolCheckEnabled))
{
rxFifo.rxFull = 0;
}
}
if (enetIfPtr->macCfgPtr->isTxAccelEnabled)
{
enet_hal_config_tx_accelerator(enetIfPtr->deviceNumber,
(enet_config_tx_accelerator_t *)&(enetIfPtr->macCfgPtr->txAcceler));
if ((enetIfPtr->macCfgPtr->txAcceler.isIpCheckEnabled) || (enetIfPtr->macCfgPtr->txAcceler.isProtocolCheckEnabled))
{
txFifo.isStoreForwardEnabled = 1;
}
}
if (enetIfPtr->macCfgPtr->isStoreAndFwEnabled)
{
rxFifo.rxFull = 0;
txFifo.isStoreForwardEnabled = 1;
}
/* Configure tx/rx FIFO with default value*/
rxFifo.rxAlmostEmpty = 4;
rxFifo.rxAlmostFull = 4;
txFifo.txAlmostEmpty = 4;
txFifo.txAlmostFull = 8;
enet_hal_config_rx_fifo(enetIfPtr->deviceNumber, &rxFifo);
enet_hal_config_tx_fifo(enetIfPtr->deviceNumber, &txFifo);
return kStatus_ENET_Success;
}
/*FUNCTION****************************************************************
*
* Function Name: enet_mac_configure_controller
* Return Value: The execution status.
* Description: Configure the ENET controller with the basic configuration.
*END*********************************************************************/
uint32_t enet_mac_configure_controller(enet_dev_if_t * enetIfPtr)
{
uint32_t macCtlCfg;
/* Check the input parameters*/
if (enetIfPtr == NULL)
{
return kStatus_ENET_InvalidInput;
}
macCtlCfg = enetIfPtr->macCfgPtr->macCtlConfigure;
/* Configure rmii/mii interface*/
enet_hal_config_rmii(enetIfPtr->deviceNumber, enetIfPtr->macCfgPtr->rmiiCfgMode,
enetIfPtr->macCfgPtr->speed, enetIfPtr->macCfgPtr->duplex, false,
(macCtlCfg & kEnetRxMiiLoopback));
/* Configure receive buffer size*/
if (enetIfPtr->macCfgPtr->isVlanEnabled)
{
enetIfPtr->maxFrameSize = kEnetMaxFrameVlanSize;
enet_hal_set_rx_max_size(enetIfPtr->deviceNumber,
enetIfPtr->macContextPtr->rxBufferSizeAligned, kEnetMaxFrameVlanSize);
}
else
{
enetIfPtr->maxFrameSize = kEnetMaxFrameSize;
enet_hal_set_rx_max_size(enetIfPtr->deviceNumber,
enetIfPtr->macContextPtr->rxBufferSizeAligned, kEnetMaxFrameSize);
}
/* Set receive controller promiscuous */
enet_hal_config_promiscuous(enetIfPtr->deviceNumber, macCtlCfg & kEnetRxPromiscuousEnable);
/* Set receive flow control*/
enet_hal_enable_flowcontrol(enetIfPtr->deviceNumber, (macCtlCfg & kEnetRxFlowControlEnable));
/* Set received PAUSE frames are forwarded/terminated*/
enet_hal_enable_pauseforward(enetIfPtr->deviceNumber, (macCtlCfg & kEnetRxPauseFwdEnable));
/* Set receive broadcast frame reject*/
enet_hal_enable_broadcastreject(enetIfPtr->deviceNumber, (macCtlCfg & kEnetRxBcRejectEnable));
/* Set padding is removed from the received frame*/
enet_hal_enable_padremove(enetIfPtr->deviceNumber, (macCtlCfg & kEnetRxPadRemoveEnable));
/* Set the crc of the received frame is stripped from the frame*/
enet_hal_enable_rxcrcforward(enetIfPtr->deviceNumber, (macCtlCfg & kEnetRxCrcFwdEnable));
/* Set receive payload length check*/
enet_hal_enable_payloadcheck(enetIfPtr->deviceNumber, (macCtlCfg & kEnetPayloadlenCheckEnable));
/* Set control sleep mode*/
enet_hal_enable_sleep(enetIfPtr->deviceNumber, (macCtlCfg & kEnetSleepModeEnable));
return kStatus_ENET_Success;
}
/*FUNCTION****************************************************************
*
* Function Name: enet_mac_init
* Return Value: The execution status.
* Description:Initialize the ENET device with the basic configuration
* When ENET is used, this function need to be called by the NET initialize
* interface.
*END*********************************************************************/
uint32_t enet_mac_init(enet_dev_if_t * enetIfPtr, enet_rxbd_config_t *rxbdCfg,
enet_txbd_config_t *txbdCfg)
{
uint32_t timeOut = 0;
uint32_t devNumber, result = 0;
/* Check the input parameters*/
if (enetIfPtr == NULL)
{
return kStatus_ENET_InvalidInput;
}
/* Get device number and check the parameter*/
devNumber = enetIfPtr->deviceNumber;
/* Store the global ENET structure for ISR input parameters for instance 0*/
if (!devNumber)
{
enetIfHandle = enetIfPtr;
}
/* Turn on ENET module clock gate */
clock_manager_set_gate(kClockModuleENET, 0U, true);
/* Reset ENET mac*/
enet_hal_reset_ethernet(devNumber);
while ((!enet_hal_is_reset_completed(devNumber)) && (timeOut < kEnetMaxTimeout))
{
time_delay(1);
timeOut++;
}
/* Check out if timeout*/
if (timeOut == kEnetMaxTimeout)
{
return kStatus_ENET_TimeOut;
}
/* Disable all ENET mac interrupt and Clear all interrupt events*/
enet_hal_config_interrupt(devNumber, kEnetAllInterrupt, false);
enet_hal_clear_interrupt(devNumber, kEnetAllInterrupt);
/* Program this station's physical address*/
enet_hal_set_mac_address(devNumber, enetIfPtr->macCfgPtr->macAddr);
/* Clear group and individual hash register*/
enet_hal_set_group_hashtable(devNumber, 0, kEnetSpecialAddressInit);
enet_hal_set_individual_hashtable(devNumber, 0, kEnetSpecialAddressInit);
/* Configure mac controller*/
result = enet_mac_configure_controller(enetIfPtr);
if(result != kStatus_ENET_Success)
{
return result;
}
/* Clear mib zero counters*/
enet_hal_clear_mib(devNumber, true);
/* Initialize FIFO and accelerator*/
result = enet_mac_configure_fifo_accel(enetIfPtr);
if(result != kStatus_ENET_Success)
{
return result;
}
/* Initialize receive buffer descriptors*/
result = enet_mac_rxbd_init(enetIfPtr, rxbdCfg);
if(result != kStatus_ENET_Success)
{
return result;
}
/* Initialize transmit buffer descriptors*/
result = enet_mac_txbd_init(enetIfPtr, txbdCfg);
if(result != kStatus_ENET_Success)
{
return result;
}
/* Initialize rmii/mii interface*/
result = enet_mac_mii_init(enetIfPtr);
if (result != kStatus_ENET_Success)
{
return result;
}
return kStatus_ENET_Success;
}
/*******************************************************************************
* EOF
******************************************************************************/

View File

@ -0,0 +1,92 @@
/*
* Copyright (c) 2013 - 2014, Freescale Semiconductor, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o 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.
*
* o Neither the name of Freescale Semiconductor, Inc. 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 HOLDER 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.
*/
#include "fsl_port_hal.h"
#include "fsl_clock_manager.h"
#include "fsl_device_registers.h"
#include "fsl_sim_hal.h"
/*******************************************************************************
* Code
******************************************************************************/
void k64f_init_eth_hardware(void)
{
uint8_t count;
/* Disable the mpu*/
BW_MPU_CESR_VLD(0);
/* Open POTR clock gate*/
for (count = 0; count < HW_PORT_INSTANCE_COUNT; count++)
{
clock_manager_set_gate(kClockModulePORT, count, true);
}
/* Configure gpio*/
port_hal_mux_control(HW_PORTA, 12, kPortMuxAlt4); /*!< ENET RMII0_RXD1/MII0_RXD1*/
port_hal_mux_control(HW_PORTA, 13, kPortMuxAlt4); /*!< ENET RMII0_RXD0/MII0_RXD0*/
port_hal_mux_control(HW_PORTA, 14, kPortMuxAlt4); /*!< ENET RMII0_CRS_DV/MII0_RXDV*/
port_hal_mux_control(HW_PORTA, 15, kPortMuxAlt4); /*!< ENET RMII0_TXEN/MII0_TXEN*/
port_hal_mux_control(HW_PORTA, 16, kPortMuxAlt4); /*!< ENET RMII0_TXD0/MII0_TXD0*/
port_hal_mux_control(HW_PORTA, 17, kPortMuxAlt4); /*!< ENET RMII0_TXD01/MII0_TXD1*/
port_hal_mux_control(HW_PORTB, 0, kPortMuxAlt4); /*!< ENET RMII0_MDIO/MII0_MDIO*/
port_hal_configure_open_drain(HW_PORTB,0, true); /*!< ENET RMII0_MDC/MII0_MDC*/
// Added for FRDM-K64F
port_hal_pull_select(HW_PORTB, 0, kPortPullUp);
port_hal_configure_pull(HW_PORTB, 0, true);
port_hal_mux_control(HW_PORTB, 1, kPortMuxAlt4);
/* Configure GPIO for MII interface */
port_hal_mux_control(HW_PORTA, 9, kPortMuxAlt4); /*!< ENET MII0_RXD3*/
port_hal_mux_control(HW_PORTA, 10, kPortMuxAlt4); /*!< ENET MII0_RXD2*/
port_hal_mux_control(HW_PORTA, 11, kPortMuxAlt4); /*!< ENET MII0_RXCLK*/
port_hal_mux_control(HW_PORTA, 24, kPortMuxAlt4); /*!< ENET MII0_TXD2*/
port_hal_mux_control(HW_PORTA, 25, kPortMuxAlt4); /*!< ENET MII0_TXCLK*/
port_hal_mux_control(HW_PORTA, 26, kPortMuxAlt4); /*!< ENET MII0_TXD3*/
port_hal_mux_control(HW_PORTA, 27, kPortMuxAlt4); /*!< ENET MII0_CRS*/
port_hal_mux_control(HW_PORTA, 28, kPortMuxAlt4); /*!< ENET MII0_TXER*/
port_hal_mux_control(HW_PORTA, 29, kPortMuxAlt4); /*!< ENET MII0_COL*/
#if FSL_FEATURE_ENET_SUPPORT_PTP
port_hal_mux_control(HW_PORTC, (16 + ENET_TIMER_CHANNEL_NUM), kPortMuxAlt4); /* ENET ENET0_1588_TMR0*/
port_hal_configure_drive_strength(HW_PORTC, (16 + ENET_TIMER_CHANNEL_NUM), kPortHighDriveStrength);
#endif
/* Open ENET clock gate*/
clock_manager_set_gate(kClockModuleENET,0,true);
/* Select the ptp timer outclk*/
clock_hal_set_clock_source(kSimClockTimeSrc, 2);
}
/*******************************************************************************
* EOF
******************************************************************************/

View File

@ -0,0 +1,864 @@
#include "lwip/opt.h"
#include "lwip/sys.h"
#include "lwip/def.h"
#include "lwip/mem.h"
#include "lwip/pbuf.h"
#include "lwip/stats.h"
#include "lwip/snmp.h"
#include "lwip/tcpip.h"
#include "netif/etharp.h"
#include "netif/ppp_oe.h"
#include "eth_arch.h"
#include "sys_arch.h"
#include "fsl_enet_driver.h"
#include "fsl_enet_hal.h"
#include "fsl_device_registers.h"
#include "fsl_phy_driver.h"
#include "fsl_interrupt_manager.h"
#include "k64f_emac_config.h"
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "mbed_interface.h"
extern IRQn_Type enet_irq_ids[HW_ENET_INSTANCE_COUNT][FSL_FEATURE_ENET_INTERRUPT_COUNT];
extern uint8_t enetIntMap[kEnetIntNum];
/********************************************************************************
* Internal data
********************************************************************************/
extern void k64f_init_eth_hardware(void);
/* K64F EMAC driver data structure */
struct k64f_enetdata {
struct netif *netif; /**< Reference back to LWIP parent netif */
sys_sem_t RxReadySem; /**< RX packet ready semaphore */
sys_sem_t TxCleanSem; /**< TX cleanup thread wakeup semaphore */
sys_mutex_t TXLockMutex; /**< TX critical section mutex */
sys_sem_t xTXDCountSem; /**< TX free buffer counting semaphore */
volatile u32_t rx_free_descs; /**< Count of free RX descriptors */
struct pbuf *rxb[ENET_RX_RING_LEN]; /**< RX pbuf pointer list, zero-copy mode */
uint8_t *rx_desc_start_addr; /**< RX descriptor start address */
uint8_t *tx_desc_start_addr; /**< TX descriptor start address */
uint8_t tx_consume_index, tx_produce_index; /**< TX buffers ring */
uint8_t rx_fill_index; /**< RX ring fill index */
struct pbuf *txb[ENET_TX_RING_LEN]; /**< TX pbuf pointer list, zero-copy mode */
void *txb_aligned[ENET_TX_RING_LEN]; /**< TX aligned buffers (if needed) */
};
static struct k64f_enetdata k64f_enetdata;
static enet_dev_if_t enetDevIf[HW_ENET_INSTANCE_COUNT];
static enet_mac_config_t g_enetMacCfg[HW_ENET_INSTANCE_COUNT] =
{
{
ENET_ETH_MAX_FLEN , /*!< enet receive buffer size*/
ENET_RX_LARGE_BUFFER_NUM, /*!< enet large receive buffer number*/
ENET_RX_RING_LEN, /*!< enet receive bd number*/
ENET_TX_RING_LEN, /*!< enet transmit bd number*/
{0}, /*!< enet mac address*/
kEnetCfgRmii, /*!< enet rmii interface*/
kEnetCfgSpeed100M, /*!< enet rmii 100M*/
kEnetCfgFullDuplex, /*!< enet rmii Full- duplex*/
/*!< enet mac control flag recommended to use enet_mac_control_flag_t
we send frame with crc so receive crc forward for data length check test*/
kEnetRxCrcFwdEnable | kEnetRxFlowControlEnable,
true, /*!< enet txaccelerator enabled*/
true, /*!< enet rxaccelerator enabled*/
false, /*!< enet store and forward*/
{false, false, true, false, true}, /*!< enet rxaccelerator config*/
{false, false, true}, /*!< enet txaccelerator config*/
true, /*!< vlan frame support*/
true, /*!< phy auto discover*/
ENET_MII_CLOCK, /*!< enet MDC clock*/
},
};
static enet_phy_config_t g_enetPhyCfg[HW_ENET_INSTANCE_COUNT] =
{
{0, false}
};
/** \brief Driver transmit and receive thread priorities
*
* Thread priorities for receive thread and TX cleanup thread. Alter
* to prioritize receive or transmit bandwidth. In a heavily loaded
* system or with LEIP_DEBUG enabled, the priorities might be better
* the same. */
#define RX_PRIORITY (osPriorityNormal)
#define TX_PRIORITY (osPriorityNormal)
#define PHY_PRIORITY (osPriorityNormal)
/** \brief Debug output formatter lock define
*
* When using FreeRTOS and with LWIP_DEBUG enabled, enabling this
* define will allow RX debug messages to not interleave with the
* TX messages (so they are actually readable). Not enabling this
* define when the system is under load will cause the output to
* be unreadable. There is a small tradeoff in performance for this
* so use it only for debug. */
//#define LOCK_RX_THREAD
/** \brief Signal used for ethernet ISR to signal packet_rx() thread.
*/
#define RX_SIGNAL 1
// K64F-specific macros
#define RX_PBUF_AUTO_INDEX (-1)
#define TX_DESC_UPDATED_MASK (0x8000)
/********************************************************************************
* Buffer management
********************************************************************************/
/** \brief Queues a pbuf into the RX descriptor list
*
* \param[in] k64f_enet Pointer to the drvier data structure
* \param[in] p Pointer to pbuf to queue
* \param[in] bidx Index to queue into
*/
static void k64f_rxqueue_pbuf(struct k64f_enetdata *k64f_enet, struct pbuf *p, int bidx)
{
enet_bd_struct_t *start = (enet_bd_struct_t *)k64f_enet->rx_desc_start_addr;
int idx;
/* Get next free descriptor index */
if (bidx == RX_PBUF_AUTO_INDEX)
idx = k64f_enet->rx_fill_index;
else
idx = bidx;
/* Setup descriptor and clear statuses */
enet_hal_init_rxbds(start + idx, (uint8_t*)p->payload, idx == ENET_RX_RING_LEN - 1);
/* Save pbuf pointer for push to network layer later */
k64f_enet->rxb[idx] = p;
/* Wrap at end of descriptor list */
idx = (idx + 1) % ENET_RX_RING_LEN;
/* Queue descriptor(s) */
k64f_enet->rx_free_descs -= 1;
if (bidx == RX_PBUF_AUTO_INDEX)
k64f_enet->rx_fill_index = idx;
enet_hal_active_rxbd(BOARD_DEBUG_ENET_INSTANCE);
LWIP_DEBUGF(UDP_LPC_EMAC | LWIP_DBG_TRACE,
("k64f_rxqueue_pbuf: pbuf packet queued: %p (free desc=%d)\n", p,
k64f_enet->rx_free_descs));
}
/** \brief Attempt to allocate and requeue a new pbuf for RX
*
* \param[in] netif Pointer to the netif structure
* \returns number of queued packets
*/
s32_t k64f_rx_queue(struct netif *netif, int idx)
{
struct k64f_enetdata *k64f_enet = netif->state;
enet_dev_if_t *enetIfPtr = (enet_dev_if_t *)&enetDevIf[BOARD_DEBUG_ENET_INSTANCE];
struct pbuf *p;
int queued = 0;
/* Attempt to requeue as many packets as possible */
while (k64f_enet->rx_free_descs > 0) {
/* Allocate a pbuf from the pool. We need to allocate at the
maximum size as we don't know the size of the yet to be
received packet. */
p = pbuf_alloc(PBUF_RAW, enetIfPtr->macCfgPtr->rxBufferSize + RX_BUF_ALIGNMENT, PBUF_RAM);
if (p == NULL) {
LWIP_DEBUGF(UDP_LPC_EMAC | LWIP_DBG_TRACE,
("k64_rx_queue: could not allocate RX pbuf (free desc=%d)\n",
k64f_enet->rx_free_descs));
return queued;
}
/* K64F note: the next line ensures that the RX buffer is properly aligned for the K64F
RX descriptors (16 bytes alignment). However, by doing so, we're effectively changing
a data structure which is internal to lwIP. This might not prove to be a good idea
in the long run, but a better fix would probably involve modifying lwIP itself */
p->payload = (void*)ENET_ALIGN((uint32_t)p->payload, RX_BUF_ALIGNMENT);
/* pbufs allocated from the RAM pool should be non-chained. */
LWIP_ASSERT("k64f_rx_queue: pbuf is not contiguous (chained)", pbuf_clen(p) <= 1);
/* Queue packet */
k64f_rxqueue_pbuf(k64f_enet, p, idx);
queued++;
}
return queued;
}
/** \brief Sets up the RX descriptor ring buffers.
*
* This function sets up the descriptor list used for receive packets.
*
* \param[in] netif Pointer to driver data structure
* \returns ERR_MEM if out of memory, ERR_OK otherwise
*/
static err_t k64f_rx_setup(struct netif *netif, enet_rxbd_config_t *rxbdCfg) {
struct k64f_enetdata *k64f_enet = netif->state;
enet_dev_if_t *enetIfPtr = (enet_dev_if_t *)&enetDevIf[BOARD_DEBUG_ENET_INSTANCE];
uint8_t *rxBdPtr;
uint32_t rxBufferSizeAligned;
// Allocate RX descriptors
rxBdPtr = (uint8_t *)calloc(1, enet_hal_get_bd_size() * enetIfPtr->macCfgPtr->rxBdNumber + ENET_BD_ALIGNMENT);
if(!rxBdPtr)
return ERR_MEM;
k64f_enet->rx_desc_start_addr = (uint8_t *)ENET_ALIGN((uint32_t)rxBdPtr, ENET_BD_ALIGNMENT);
k64f_enet->rx_free_descs = enetIfPtr->macCfgPtr->rxBdNumber;
k64f_enet->rx_fill_index = 0;
rxBufferSizeAligned = ENET_ALIGN(enetIfPtr->macCfgPtr->rxBufferSize, ENET_RX_BUFFER_ALIGNMENT);
enetIfPtr->macContextPtr->rxBufferSizeAligned = rxBufferSizeAligned;
rxbdCfg->rxBdPtrAlign = k64f_enet->rx_desc_start_addr;
rxbdCfg->rxBdNum = enetIfPtr->macCfgPtr->rxBdNumber;
rxbdCfg->rxBufferNum = enetIfPtr->macCfgPtr->rxBdNumber;
k64f_rx_queue(netif, RX_PBUF_AUTO_INDEX);
return ERR_OK;
}
/** \brief Sets up the TX descriptor ring buffers.
*
* This function sets up the descriptor list used for transmit packets.
*
* \param[in] netif Pointer to driver data structure
* \returns ERR_MEM if out of memory, ERR_OK otherwise
*/
static err_t k64f_tx_setup(struct netif *netif, enet_txbd_config_t *txbdCfg) {
struct k64f_enetdata *k64f_enet = netif->state;
enet_dev_if_t *enetIfPtr = (enet_dev_if_t *)&enetDevIf[BOARD_DEBUG_ENET_INSTANCE];
uint8_t *txBdPtr;
// Allocate TX descriptors
txBdPtr = (uint8_t *)calloc(1, enet_hal_get_bd_size() * enetIfPtr->macCfgPtr->txBdNumber + ENET_BD_ALIGNMENT);
if(!txBdPtr)
return ERR_MEM;
k64f_enet->tx_desc_start_addr = (uint8_t *)ENET_ALIGN((uint32_t)txBdPtr, ENET_BD_ALIGNMENT);
k64f_enet->tx_consume_index = k64f_enet->tx_produce_index = 0;
txbdCfg->txBdPtrAlign = k64f_enet->tx_desc_start_addr;
txbdCfg->txBufferNum = enetIfPtr->macCfgPtr->txBdNumber;
txbdCfg->txBufferSizeAlign = ENET_ALIGN(enetIfPtr->maxFrameSize, ENET_TX_BUFFER_ALIGNMENT);
// Make the TX descriptor ring circular
enet_hal_init_txbds(k64f_enet->tx_desc_start_addr + enet_hal_get_bd_size() * (ENET_TX_RING_LEN - 1), 1);
return ERR_OK;
}
/** \brief Free TX buffers that are complete
*
* \param[in] k64f_enet Pointer to driver data structure
*/
static void k64f_tx_reclaim(struct k64f_enetdata *k64f_enet)
{
uint8_t i;
volatile enet_bd_struct_t * bdPtr = (enet_bd_struct_t *)k64f_enet->tx_desc_start_addr;
/* Get exclusive access */
sys_mutex_lock(&k64f_enet->TXLockMutex);
// Traverse all descriptors, looking for the ones modified by the uDMA
i = k64f_enet->tx_consume_index;
while(i != k64f_enet->tx_produce_index) {
if (bdPtr[i].controlExtend2 & TX_DESC_UPDATED_MASK) { // descriptor updated by uDMA
if (k64f_enet->txb_aligned[i]) {
free(k64f_enet->txb_aligned[i]);
k64f_enet->txb_aligned[i] = NULL;
} else if (k64f_enet->txb[i]) {
pbuf_free(k64f_enet->txb[i]);
k64f_enet->txb[i] = NULL;
}
osSemaphoreRelease(k64f_enet->xTXDCountSem.id);
bdPtr[i].controlExtend2 &= ~TX_DESC_UPDATED_MASK;
}
i = (i + 1) % ENET_TX_RING_LEN;
}
k64f_enet->tx_consume_index = i;
/* Restore access */
sys_mutex_unlock(&k64f_enet->TXLockMutex);
}
/** \brief Low level init of the MAC and PHY.
*
* \param[in] netif Pointer to LWIP netif structure
*/
static err_t low_level_init(struct netif *netif)
{
enet_dev_if_t * enetIfPtr;
uint32_t device = BOARD_DEBUG_ENET_INSTANCE;
enet_rxbd_config_t rxbdCfg;
enet_txbd_config_t txbdCfg;
enet_phy_speed_t phy_speed;
enet_phy_duplex_t phy_duplex;
k64f_init_eth_hardware();
/* Initialize device*/
enetIfPtr = (enet_dev_if_t *)&enetDevIf[device];
enetIfPtr->deviceNumber = device;
enetIfPtr->macCfgPtr = &g_enetMacCfg[device];
enetIfPtr->phyCfgPtr = &g_enetPhyCfg[device];
enetIfPtr->macApiPtr = &g_enetMacApi;
enetIfPtr->phyApiPtr = (void *)&g_enetPhyApi;
memcpy(enetIfPtr->macCfgPtr->macAddr, (char*)netif->hwaddr, kEnetMacAddrLen);
/* Allocate buffer for ENET mac context*/
enetIfPtr->macContextPtr = (enet_mac_context_t *)calloc(1, sizeof(enet_mac_context_t));
if (!enetIfPtr->macContextPtr) {
return ERR_BUF;
}
/* Initialize enet buffers*/
if(k64f_rx_setup(netif, &rxbdCfg) != ERR_OK) {
return ERR_BUF;
}
/* Initialize enet buffers*/
if(k64f_tx_setup(netif, &txbdCfg) != ERR_OK) {
return ERR_BUF;
}
/* Initialize enet module*/
if (enet_mac_init(enetIfPtr, &rxbdCfg, &txbdCfg) == kStatus_ENET_Success)
{
/* Initialize PHY*/
if (enetIfPtr->macCfgPtr->isPhyAutoDiscover) {
if (((enet_phy_api_t *)(enetIfPtr->phyApiPtr))->phy_auto_discover(enetIfPtr) != kStatus_PHY_Success)
return ERR_IF;
}
if (((enet_phy_api_t *)(enetIfPtr->phyApiPtr))->phy_init(enetIfPtr) != kStatus_PHY_Success)
return ERR_IF;
enetIfPtr->isInitialized = true;
}
else
{
// TODOETH: cleanup memory
return ERR_IF;
}
/* Get link information from PHY */
phy_get_link_speed(enetIfPtr, &phy_speed);
phy_get_link_duplex(enetIfPtr, &phy_duplex);
BW_ENET_RCR_RMII_10T(enetIfPtr->deviceNumber, phy_speed == kEnetSpeed10M ? kEnetCfgSpeed10M : kEnetCfgSpeed100M);
BW_ENET_TCR_FDEN(enetIfPtr->deviceNumber, phy_duplex == kEnetFullDuplex ? kEnetCfgFullDuplex : kEnetCfgHalfDuplex);
/* Enable Ethernet module*/
enet_hal_config_ethernet(device, true, true);
/* Active Receive buffer descriptor must be done after module enable*/
enet_hal_active_rxbd(enetIfPtr->deviceNumber);
return ERR_OK;
}
/********************************************************************************
* LWIP port
********************************************************************************/
/** \brief Ethernet receive interrupt handler
*
* This function handles the receive interrupt of K64F.
*/
void enet_mac_rx_isr(void *enetIfPtr)
{
/* Clear interrupt */
enet_hal_clear_interrupt(((enet_dev_if_t *)enetIfPtr)->deviceNumber, kEnetRxFrameInterrupt);
sys_sem_signal(&k64f_enetdata.RxReadySem);
}
void enet_mac_tx_isr(void *enetIfPtr)
{
/*Clear interrupt*/
enet_hal_clear_interrupt(((enet_dev_if_t *)enetIfPtr)->deviceNumber, kEnetTxFrameInterrupt);
sys_sem_signal(&k64f_enetdata.TxCleanSem);
}
/**
* This function is the ethernet packet send function. It calls
* etharp_output after checking link status.
*
* \param[in] netif the lwip network interface structure for this enetif
* \param[in] q Pointer to pbug to send
* \param[in] ipaddr IP address
* \return ERR_OK or error code
*/
err_t k64f_etharp_output(struct netif *netif, struct pbuf *q, ip_addr_t *ipaddr)
{
/* Only send packet is link is up */
if (netif->flags & NETIF_FLAG_LINK_UP)
return etharp_output(netif, q, ipaddr);
return ERR_CONN;
}
/** \brief Allocates a pbuf and returns the data from the incoming packet.
*
* \param[in] netif the lwip network interface structure
* \param[in] idx index of packet to be read
* \return a pbuf filled with the received packet (including MAC header)
*/
static struct pbuf *k64f_low_level_input(struct netif *netif, int idx)
{
struct k64f_enetdata *k64f_enet = netif->state;
enet_bd_struct_t * bdPtr = (enet_bd_struct_t*)k64f_enet->rx_desc_start_addr;
struct pbuf *p = NULL;
u32_t length = 0, orig_length;
const u16_t err_mask = kEnetRxBdTrunc | kEnetRxBdCrc | kEnetRxBdNoOctet | kEnetRxBdLengthViolation;
#ifdef LOCK_RX_THREAD
/* Get exclusive access */
sys_mutex_lock(&k64f_enet->TXLockMutex);
#endif
/* Determine if a frame has been received */
if ((bdPtr[idx].control & err_mask) != 0) {
#if LINK_STATS
if ((bdPtr[idx].control & kEnetRxBdLengthViolation) != 0)
LINK_STATS_INC(link.lenerr);
else
LINK_STATS_INC(link.chkerr);
#endif
LINK_STATS_INC(link.drop);
/* Re-queue the same buffer */
k64f_enet->rx_free_descs++;
p = k64f_enet->rxb[idx];
k64f_enet->rxb[idx] = NULL;
k64f_rxqueue_pbuf(k64f_enet, p, idx);
p = NULL;
} else {
/* A packet is waiting, get length */
length = enet_hal_get_bd_length(bdPtr + idx);
/* Zero-copy */
p = k64f_enet->rxb[idx];
orig_length = p->len;
p->len = (u16_t) length;
/* Free pbuf from descriptor */
k64f_enet->rxb[idx] = NULL;
k64f_enet->rx_free_descs++;
/* Attempt to queue new buffer */
if (k64f_rx_queue(netif, idx) == 0) {
/* Drop frame (out of memory) */
LINK_STATS_INC(link.drop);
/* Re-queue the same buffer */
p->len = orig_length;
k64f_rxqueue_pbuf(k64f_enet, p, idx);
LWIP_DEBUGF(UDP_LPC_EMAC | LWIP_DBG_TRACE,
("k64f_low_level_input: Packet index %d dropped for OOM\n",
idx));
#ifdef LOCK_RX_THREAD
sys_mutex_unlock(&k64f_enet->TXLockMutex);
#endif
return NULL;
}
LWIP_DEBUGF(UDP_LPC_EMAC | LWIP_DBG_TRACE,
("k64f_low_level_input: Packet received: %p, size %d (index=%d)\n",
p, length, idx));
/* Save size */
p->tot_len = (u16_t) length;
LINK_STATS_INC(link.recv);
}
#ifdef LOCK_RX_THREAD
sys_mutex_unlock(&k64f_enet->TXLockMutex);
#endif
return p;
}
/** \brief Attempt to read a packet from the EMAC interface.
*
* \param[in] netif the lwip network interface structure
* \param[in] idx index of packet to be read
*/
void k64f_enetif_input(struct netif *netif, int idx)
{
struct eth_hdr *ethhdr;
struct pbuf *p;
/* move received packet into a new pbuf */
p = k64f_low_level_input(netif, idx);
if (p == NULL)
return;
/* points to packet payload, which starts with an Ethernet header */
ethhdr = (struct eth_hdr*)p->payload;
switch (htons(ethhdr->type)) {
case ETHTYPE_IP:
case ETHTYPE_ARP:
#if PPPOE_SUPPORT
case ETHTYPE_PPPOEDISC:
case ETHTYPE_PPPOE:
#endif /* PPPOE_SUPPORT */
/* full packet send to tcpip_thread to process */
if (netif->input(p, netif) != ERR_OK) {
LWIP_DEBUGF(NETIF_DEBUG, ("k64f_enetif_input: IP input error\n"));
/* Free buffer */
pbuf_free(p);
}
break;
default:
/* Return buffer */
pbuf_free(p);
break;
}
}
/** \brief Packet reception task
*
* This task is called when a packet is received. It will
* pass the packet to the LWIP core.
*
* \param[in] pvParameters pointer to the interface data
*/
static void packet_rx(void* pvParameters) {
struct k64f_enetdata *k64f_enet = pvParameters;
volatile enet_bd_struct_t * bdPtr = (enet_bd_struct_t*)k64f_enet->rx_desc_start_addr;
int idx = 0;
while (1) {
/* Wait for receive task to wakeup */
sys_arch_sem_wait(&k64f_enet->RxReadySem, 0);
if ((bdPtr[idx].control & kEnetRxBdEmpty) == 0) {
k64f_enetif_input(k64f_enet->netif, idx);
idx = (idx + 1) % ENET_RX_RING_LEN;
}
}
}
/** \brief Transmit cleanup task
*
* This task is called when a transmit interrupt occurs and
* reclaims the pbuf and descriptor used for the packet once
* the packet has been transferred.
*
* \param[in] pvParameters pointer to the interface data
*/
static void packet_tx(void* pvParameters) {
struct k64f_enetdata *k64f_enet = pvParameters;
while (1) {
/* Wait for transmit cleanup task to wakeup */
sys_arch_sem_wait(&k64f_enet->TxCleanSem, 0);
// TODOETH: handle TX underrun?
k64f_tx_reclaim(k64f_enet);
}
}
/** \brief Polls if an available TX descriptor is ready. Can be used to
* determine if the low level transmit function will block.
*
* \param[in] netif the lwip network interface structure
* \return 0 if no descriptors are read, or >0
*/
s32_t k64f_tx_ready(struct netif *netif)
{
struct k64f_enetdata *k64f_enet = netif->state;
s32_t fb;
u32_t idx, cidx;
cidx = k64f_enet->tx_consume_index;
idx = k64f_enet->tx_produce_index;
/* Determine number of free buffers */
if (idx == cidx)
fb = ENET_TX_RING_LEN;
else if (cidx > idx)
fb = (ENET_TX_RING_LEN - 1) -
((idx + ENET_TX_RING_LEN) - cidx);
else
fb = (ENET_TX_RING_LEN - 1) - (cidx - idx);
return fb;
}
/*FUNCTION****************************************************************
*
* Function Name: enet_hal_update_txbds
* Description: Update ENET transmit buffer descriptors.
*END*********************************************************************/
void k64f_update_txbds(struct k64f_enetdata *k64f_enet, int idx, uint8_t *buffer, uint16_t length, bool isLast)
{
volatile enet_bd_struct_t * bdPtr = (enet_bd_struct_t *)(k64f_enet->tx_desc_start_addr + idx * enet_hal_get_bd_size());
bdPtr->length = HTONS(length); /* Set data length*/
bdPtr->buffer = (uint8_t *)HTONL((uint32_t)buffer); /* Set data buffer*/
if (isLast)
bdPtr->control |= kEnetTxBdLast;
else
bdPtr->control &= ~kEnetTxBdLast;
bdPtr->controlExtend1 |= kEnetTxBdTxInterrupt;
bdPtr->controlExtend2 &= ~TX_DESC_UPDATED_MASK; // descriptor not updated by DMA
bdPtr->control |= kEnetTxBdTransmitCrc | kEnetTxBdReady;
}
/** \brief Low level output of a packet. Never call this from an
* interrupt context, as it may block until TX descriptors
* become available.
*
* \param[in] netif the lwip network interface structure for this netif
* \param[in] p the MAC packet to send (e.g. IP packet including MAC addresses and type)
* \return ERR_OK if the packet could be sent or an err_t value if the packet couldn't be sent
*/
static err_t k64f_low_level_output(struct netif *netif, struct pbuf *p)
{
struct k64f_enetdata *k64f_enet = netif->state;
struct pbuf *q;
u32_t idx;
s32_t dn;
uint8_t *psend = NULL, *dst;
/* Get free TX buffer index */
idx = k64f_enet->tx_produce_index;
/* Check the pbuf chain for payloads that are not 8-byte aligned.
If found, a new properly aligned buffer needs to be allocated
and the data copied there */
for (q = p; q != NULL; q = q->next)
if (((u32_t)q->payload & (TX_BUF_ALIGNMENT - 1)) != 0)
break;
if (q != NULL) {
// Allocate properly aligned buffer
psend = (uint8_t*)malloc(p->tot_len);
if (NULL == psend)
return ERR_MEM;
LWIP_ASSERT("k64f_low_level_output: buffer not properly aligned", ((u32_t)psend & (TX_BUF_ALIGNMENT - 1)) == 0);
for (q = p, dst = psend; q != NULL; q = q->next) {
MEMCPY(dst, q->payload, q->len);
dst += q->len;
}
k64f_enet->txb_aligned[idx] = psend;
dn = 1;
} else {
k64f_enet->txb_aligned[idx] = NULL;
dn = (s32_t) pbuf_clen(p);
pbuf_ref(p);
}
/* Wait until enough descriptors are available for the transfer. */
/* THIS WILL BLOCK UNTIL THERE ARE ENOUGH DESCRIPTORS AVAILABLE */
while (dn > k64f_tx_ready(netif))
osSemaphoreWait(k64f_enet->xTXDCountSem.id, osWaitForever);
/* Get exclusive access */
sys_mutex_lock(&k64f_enet->TXLockMutex);
/* Setup transfers */
q = p;
while (dn > 0) {
dn--;
if (psend != NULL) {
k64f_update_txbds(k64f_enet, idx, psend, p->tot_len, 1);
k64f_enet->txb[idx] = NULL;
LWIP_DEBUGF(UDP_LPC_EMAC | LWIP_DBG_TRACE,
("k64f_low_level_output: aligned packet(%p) sent"
" size = %d (index=%d)\n", psend, p->tot_len, idx));
} else {
LWIP_ASSERT("k64f_low_level_output: buffer not properly aligned", ((u32_t)q->payload & 0x07) == 0);
/* Only save pointer to free on last descriptor */
if (dn == 0) {
/* Save size of packet and signal it's ready */
k64f_update_txbds(k64f_enet, idx, q->payload, q->len, 1);
k64f_enet->txb[idx] = p;
}
else {
/* Save size of packet, descriptor is not last */
k64f_update_txbds(k64f_enet, idx, q->payload, q->len, 0);
k64f_enet->txb[idx] = NULL;
}
LWIP_DEBUGF(UDP_LPC_EMAC | LWIP_DBG_TRACE,
("k64f_low_level_output: pbuf packet(%p) sent, chain#=%d,"
" size = %d (index=%d)\n", q->payload, dn, q->len, idx));
}
q = q->next;
idx = (idx + 1) % ENET_TX_RING_LEN;
}
k64f_enet->tx_produce_index = idx;
enet_hal_active_txbd(BOARD_DEBUG_ENET_INSTANCE);
LINK_STATS_INC(link.xmit);
/* Restore access */
sys_mutex_unlock(&k64f_enet->TXLockMutex);
return ERR_OK;
}
/*******************************************************************************
* PHY task: monitor link
*******************************************************************************/
#define PHY_TASK_PERIOD_MS 200
#define STATE_UNKNOWN (-1)
typedef struct {
int connected;
enet_phy_speed_t speed;
enet_phy_duplex_t duplex;
} PHY_STATE;
static void k64f_phy_task(void *data) {
struct netif *netif = (struct netif*)data;
bool connection_status;
enet_dev_if_t * enetIfPtr = (enet_dev_if_t*)&enetDevIf[BOARD_DEBUG_ENET_INSTANCE];
PHY_STATE crt_state = {STATE_UNKNOWN, (enet_phy_speed_t)STATE_UNKNOWN, (enet_phy_duplex_t)STATE_UNKNOWN};
PHY_STATE prev_state;
prev_state = crt_state;
while (true) {
// Get current status
phy_get_link_status(enetIfPtr, &connection_status);
crt_state.connected = connection_status ? 1 : 0;
phy_get_link_speed(enetIfPtr, &crt_state.speed);
phy_get_link_duplex(enetIfPtr, &crt_state.duplex);
// Compare with previous state
if (crt_state.connected != prev_state.connected) {
if (crt_state.connected)
tcpip_callback_with_block((tcpip_callback_fn)netif_set_link_up, (void*) netif, 1);
else
tcpip_callback_with_block((tcpip_callback_fn)netif_set_link_down, (void*) netif, 1);
}
if (crt_state.speed != prev_state.speed)
BW_ENET_RCR_RMII_10T(enetIfPtr->deviceNumber, crt_state.speed == kEnetSpeed10M ? kEnetCfgSpeed10M : kEnetCfgSpeed100M);
// TODO: duplex change requires disable/enable of Ethernet interface, to be implemented
prev_state = crt_state;
osDelay(PHY_TASK_PERIOD_MS);
}
}
/**
* Should be called at the beginning of the program to set up the
* network interface.
*
* This function should be passed as a parameter to netif_add().
*
* @param[in] netif the lwip network interface structure for this netif
* @return ERR_OK if the loopif is initialized
* ERR_MEM if private data couldn't be allocated
* any other err_t on error
*/
err_t eth_arch_enetif_init(struct netif *netif)
{
err_t err;
LWIP_ASSERT("netif != NULL", (netif != NULL));
k64f_enetdata.netif = netif;
/* set MAC hardware address */
#if (MBED_MAC_ADDRESS_SUM != MBED_MAC_ADDR_INTERFACE)
netif->hwaddr[0] = MBED_MAC_ADDR_0;
netif->hwaddr[1] = MBED_MAC_ADDR_1;
netif->hwaddr[2] = MBED_MAC_ADDR_2;
netif->hwaddr[3] = MBED_MAC_ADDR_3;
netif->hwaddr[4] = MBED_MAC_ADDR_4;
netif->hwaddr[5] = MBED_MAC_ADDR_5;
#else
mbed_mac_address((char *)netif->hwaddr);
#endif
netif->hwaddr_len = ETHARP_HWADDR_LEN;
/* maximum transfer unit */
netif->mtu = 1500;
/* device capabilities */
// TODOETH: check if the flags are correct below
netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET | NETIF_FLAG_IGMP;
/* Initialize the hardware */
netif->state = &k64f_enetdata;
err = low_level_init(netif);
if (err != ERR_OK)
return err;
#if LWIP_NETIF_HOSTNAME
/* Initialize interface hostname */
netif->hostname = "lwipk64f";
#endif /* LWIP_NETIF_HOSTNAME */
netif->name[0] = 'e';
netif->name[1] = 'n';
netif->output = k64f_etharp_output;
netif->linkoutput = k64f_low_level_output;
/* CMSIS-RTOS, start tasks */
#ifdef CMSIS_OS_RTX
memset(k64f_enetdata.xTXDCountSem.data, 0, sizeof(k64f_enetdata.xTXDCountSem.data));
k64f_enetdata.xTXDCountSem.def.semaphore = k64f_enetdata.xTXDCountSem.data;
#endif
k64f_enetdata.xTXDCountSem.id = osSemaphoreCreate(&k64f_enetdata.xTXDCountSem.def, ENET_TX_RING_LEN);
LWIP_ASSERT("xTXDCountSem creation error", (k64f_enetdata.xTXDCountSem.id != NULL));
err = sys_mutex_new(&k64f_enetdata.TXLockMutex);
LWIP_ASSERT("TXLockMutex creation error", (err == ERR_OK));
/* Packet receive task */
err = sys_sem_new(&k64f_enetdata.RxReadySem, 0);
LWIP_ASSERT("RxReadySem creation error", (err == ERR_OK));
sys_thread_new("receive_thread", packet_rx, netif->state, DEFAULT_THREAD_STACKSIZE, RX_PRIORITY);
/* Transmit cleanup task */
err = sys_sem_new(&k64f_enetdata.TxCleanSem, 0);
LWIP_ASSERT("TxCleanSem creation error", (err == ERR_OK));
sys_thread_new("txclean_thread", packet_tx, netif->state, DEFAULT_THREAD_STACKSIZE, TX_PRIORITY);
/* PHY monitoring task */
sys_thread_new("phy_thread", k64f_phy_task, netif, DEFAULT_THREAD_STACKSIZE, PHY_PRIORITY);
/* Allow the PHY task to detect the initial link state and set up the proper flags */
osDelay(10);
return ERR_OK;
}
void eth_arch_enable_interrupts(void) {
enet_hal_config_interrupt(BOARD_DEBUG_ENET_INSTANCE, (kEnetTxFrameInterrupt | kEnetRxFrameInterrupt), true);
interrupt_enable(enet_irq_ids[BOARD_DEBUG_ENET_INSTANCE][enetIntMap[kEnetRxfInt]]);
interrupt_enable(enet_irq_ids[BOARD_DEBUG_ENET_INSTANCE][enetIntMap[kEnetTxfInt]]);
}
void eth_arch_disable_interrupts(void) {
interrupt_disable(enet_irq_ids[BOARD_DEBUG_ENET_INSTANCE][enetIntMap[kEnetRxfInt]]);
interrupt_disable(enet_irq_ids[BOARD_DEBUG_ENET_INSTANCE][enetIntMap[kEnetTxfInt]]);
}
/**
* @}
*/
/* --------------------------------- End Of File ------------------------------ */

View File

@ -0,0 +1,47 @@
/*
* Copyright (c) 2013 - 2014, Freescale Semiconductor, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o 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.
*
* o Neither the name of Freescale Semiconductor, Inc. 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 HOLDER 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.
*/
#ifndef K64F_EMAC_CONFIG_H__
#define K64F_EMAC_CONFIG_H__
#define ENET_RX_RING_LEN (16)
#define ENET_TX_RING_LEN (8)
#define ENET_RX_LARGE_BUFFER_NUM (0)
#define ENET_RX_BUFFER_ALIGNMENT (16)
#define ENET_TX_BUFFER_ALIGNMENT (16)
#define ENET_BD_ALIGNMENT (16)
#define ENET_MII_CLOCK (2500000L)
#define RX_BUF_ALIGNMENT (16)
#define TX_BUF_ALIGNMENT (8)
#define BOARD_DEBUG_ENET_INSTANCE (0)
#define ENET_ETH_MAX_FLEN (1522) // recommended size for a VLAN frame
#endif // #define K64F_EMAC_CONFIG_H__

View File

@ -0,0 +1,29 @@
/* Copyright (C) 2012 mbed.org, MIT License
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
* and associated documentation files (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge, publish, distribute,
* sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or
* substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef LWIPOPTS_CONF_H
#define LWIPOPTS_CONF_H
#include "k64f_emac_config.h"
#define LWIP_TRANSPORT_ETHERNET 1
#define ETH_PAD_SIZE 2
#define MEM_SIZE (ENET_RX_RING_LEN * (ENET_ETH_MAX_FLEN + RX_BUF_ALIGNMENT) + ENET_TX_RING_LEN * ENET_ETH_MAX_FLEN)
#endif

View File

@ -34,7 +34,7 @@
#include "netif/ppp_oe.h"
#include "lpc17xx_emac.h"
#include "lpc17_emac.h"
#include "eth_arch.h"
#include "lpc_emac_config.h"
#include "lpc_phy.h"
#include "sys_arch.h"
@ -156,92 +156,6 @@ struct lpc_enetdata {
*/
ETHMEM_SECTION struct lpc_enetdata lpc_enetdata;
/* Write a value via the MII link (non-blocking) */
void lpc_mii_write_noblock(u32_t PhyReg, u32_t Value)
{
/* Write value at PHY address and register */
LPC_EMAC->MADR = (LPC_PHYDEF_PHYADDR << 8) | PhyReg;
LPC_EMAC->MWTD = Value;
}
/* Write a value via the MII link (blocking) */
err_t lpc_mii_write(u32_t PhyReg, u32_t Value)
{
u32_t mst = 250;
err_t sts = ERR_OK;
/* Write value at PHY address and register */
lpc_mii_write_noblock(PhyReg, Value);
/* Wait for unbusy status */
while (mst > 0) {
sts = LPC_EMAC->MIND;
if ((sts & EMAC_MIND_BUSY) == 0)
mst = 0;
else {
mst--;
osDelay(1);
}
}
if (sts != 0)
sts = ERR_TIMEOUT;
return sts;
}
/* Reads current MII link busy status */
u32_t lpc_mii_is_busy(void)
{
return (u32_t) (LPC_EMAC->MIND & EMAC_MIND_BUSY);
}
/* Starts a read operation via the MII link (non-blocking) */
u32_t lpc_mii_read_data(void)
{
u32_t data = LPC_EMAC->MRDD;
LPC_EMAC->MCMD = 0;
return data;
}
/* Starts a read operation via the MII link (non-blocking) */
void lpc_mii_read_noblock(u32_t PhyReg)
{
/* Read value at PHY address and register */
LPC_EMAC->MADR = (LPC_PHYDEF_PHYADDR << 8) | PhyReg;
LPC_EMAC->MCMD = EMAC_MCMD_READ;
}
/* Read a value via the MII link (blocking) */
err_t lpc_mii_read(u32_t PhyReg, u32_t *data)
{
u32_t mst = 250;
err_t sts = ERR_OK;
/* Read value at PHY address and register */
lpc_mii_read_noblock(PhyReg);
/* Wait for unbusy status */
while (mst > 0) {
sts = LPC_EMAC->MIND & ~EMAC_MIND_MII_LINK_FAIL;
if ((sts & EMAC_MIND_BUSY) == 0) {
mst = 0;
*data = LPC_EMAC->MRDD;
} else {
mst--;
osDelay(1);
}
}
LPC_EMAC->MCMD = 0;
if (sts != 0)
sts = ERR_TIMEOUT;
return sts;
}
/** \brief Queues a pbuf into the RX descriptor list
*
* \param[in] lpc_enetif Pointer to the drvier data structure
@ -1043,7 +957,7 @@ osTimerDef(phy_update, phy_update);
* ERR_MEM if private data couldn't be allocated
* any other err_t on error
*/
err_t lpc_enetif_init(struct netif *netif)
err_t eth_arch_enetif_init(struct netif *netif)
{
err_t err;
@ -1116,6 +1030,15 @@ err_t lpc_enetif_init(struct netif *netif)
return ERR_OK;
}
void eth_arch_enable_interrupts(void) {
NVIC_SetPriority(ENET_IRQn, ((0x01 << 3) | 0x01));
NVIC_EnableIRQ(ENET_IRQn);
}
void eth_arch_disable_interrupts(void) {
NVIC_DisableIRQ(ENET_IRQn);
}
/**
* @}
*/

View File

@ -29,6 +29,7 @@
#include "lwip/snmp.h"
#include "lpc_emac_config.h"
#include "lpc_phy.h"
#include "lpc17xx_emac.h"
/** @defgroup dp83848_phy PHY status and control for the DP83848.
* @ingroup lwip_phy
@ -130,6 +131,94 @@ static u32_t phy_id;
/** \brief Temporary holder of link status for LAN7420 */
static u32_t phy_lan7420_sts_tmp;
/* Write a value via the MII link (non-blocking) */
void lpc_mii_write_noblock(u32_t PhyReg, u32_t Value)
{
/* Write value at PHY address and register */
LPC_EMAC->MADR = (LPC_PHYDEF_PHYADDR << 8) | PhyReg;
LPC_EMAC->MWTD = Value;
}
/* Write a value via the MII link (blocking) */
err_t lpc_mii_write(u32_t PhyReg, u32_t Value)
{
u32_t mst = 250;
err_t sts = ERR_OK;
/* Write value at PHY address and register */
lpc_mii_write_noblock(PhyReg, Value);
/* Wait for unbusy status */
while (mst > 0) {
sts = LPC_EMAC->MIND;
if ((sts & EMAC_MIND_BUSY) == 0)
mst = 0;
else {
mst--;
osDelay(1);
}
}
if (sts != 0)
sts = ERR_TIMEOUT;
return sts;
}
/* Reads current MII link busy status */
u32_t lpc_mii_is_busy(void)
{
return (u32_t) (LPC_EMAC->MIND & EMAC_MIND_BUSY);
}
/* Starts a read operation via the MII link (non-blocking) */
u32_t lpc_mii_read_data(void)
{
u32_t data = LPC_EMAC->MRDD;
LPC_EMAC->MCMD = 0;
return data;
}
/* Starts a read operation via the MII link (non-blocking) */
void lpc_mii_read_noblock(u32_t PhyReg)
{
/* Read value at PHY address and register */
LPC_EMAC->MADR = (LPC_PHYDEF_PHYADDR << 8) | PhyReg;
LPC_EMAC->MCMD = EMAC_MCMD_READ;
}
/* Read a value via the MII link (blocking) */
err_t lpc_mii_read(u32_t PhyReg, u32_t *data)
{
u32_t mst = 250;
err_t sts = ERR_OK;
/* Read value at PHY address and register */
lpc_mii_read_noblock(PhyReg);
/* Wait for unbusy status */
while (mst > 0) {
sts = LPC_EMAC->MIND & ~EMAC_MIND_MII_LINK_FAIL;
if ((sts & EMAC_MIND_BUSY) == 0) {
mst = 0;
*data = LPC_EMAC->MRDD;
} else {
mst--;
osDelay(1);
}
}
LPC_EMAC->MCMD = 0;
if (sts != 0)
sts = ERR_TIMEOUT;
return sts;
}
/** \brief Update PHY status from passed value
*
* This function updates the current PHY status based on the

View File

@ -19,6 +19,12 @@
#ifndef LWIPOPTS_CONF_H
#define LWIPOPTS_CONF_H
#define LWIP_TRANSPORT_ETHERNET 1
#define LWIP_TRANSPORT_ETHERNET 1
#if defined(TARGET_LPC4088)
#define MEM_SIZE 15360
#elif defined(TARGET_LPC1768)
#define MEM_SIZE 16362
#endif
#endif

View File

@ -1,51 +0,0 @@
/**********************************************************************
* $Id$ lpc17_emac.h 2011-11-20
*//**
* @file lpc17_emac.h
* @brief LPC17 ethernet driver header file for LWIP
* @version 1.0
* @date 20. Nov. 2011
* @author NXP MCU SW Application Team
*
* Copyright(C) 2011, NXP Semiconductor
* All rights reserved.
*
***********************************************************************
* Software that is described herein is for illustrative purposes only
* which provides customers with programming information regarding the
* products. This software is supplied "AS IS" without any warranties.
* NXP Semiconductors assumes no responsibility or liability for the
* use of the software, conveys no license or title under any patent,
* copyright, or mask work right to the product. NXP Semiconductors
* reserves the right to make changes in the software without
* notification. NXP Semiconductors also make no representation or
* warranty that such application will be suitable for the specified
* use without further testing or modification.
**********************************************************************/
#ifndef __LPC17_EMAC_H
#define __LPC17_EMAC_H
#include "lwip/opt.h"
#include "lwip/netif.h"
#ifdef __cplusplus
extern "C"
{
#endif
/* These functions are only visible when not using an RTOS */
#if NO_SYS == 1
void lpc_enetif_input(struct netif *netif);
s32_t lpc_tx_ready(struct netif *netif);
s32_t lpc_rx_queue(struct netif *netif);
void lpc_tx_reclaim(struct netif *netif);
#endif
err_t lpc_enetif_init(struct netif *netif);
#ifdef __cplusplus
}
#endif
#endif /* __LPC17_EMAC_H */

View File

@ -186,8 +186,10 @@ struct mem {
# else
# define ETHMEM_SECTION __attribute__((section("AHBSRAM1"),aligned))
# endif
#else
#elif defined(TARGET_LPC1768)
# define ETHMEM_SECTION __attribute((section("AHBSRAM0")))
#else
# define ETHMEM_SECTION
#endif
/** the heap. we need one struct mem at the end and some room for alignment */
@ -609,10 +611,10 @@ mem_malloc(mem_size_t size)
sys_mutex_unlock(&mem_mutex);
LWIP_ASSERT("mem_malloc: allocated memory not above ram_end.",
(mem_ptr_t)mem + SIZEOF_STRUCT_MEM + size <= (mem_ptr_t)ram_end);
LWIP_ASSERT("mem_malloc: allocated memory properly aligned.",
((mem_ptr_t)mem + SIZEOF_STRUCT_MEM) % MEM_ALIGNMENT == 0);
LWIP_ASSERT("mem_malloc: allocated memory properly aligned.",
((mem_ptr_t)mem + SIZEOF_STRUCT_MEM) % MEM_ALIGNMENT == 0);
LWIP_ASSERT("mem_malloc: sanity check alignment",
(((mem_ptr_t)mem) & (MEM_ALIGNMENT-1)) == 0);
(((mem_ptr_t)mem) & (MEM_ALIGNMENT-1)) == 0);
return (u8_t *)mem + SIZEOF_STRUCT_MEM;
}

View File

@ -168,7 +168,7 @@ static u8_t *const memp_bases[] = {
#if defined(TARGET_LPC1768)
# define ETHMEM_SECTION __attribute((section("AHBSRAM1")))
#else
#elif defined(TARGET_LPC4088) || defined(TARGET_K64F)
# define ETHMEM_SECTION
#endif

View File

@ -115,6 +115,7 @@ void mem_free(void *mem);
#define LWIP_MEM_ALIGN(addr) ((void *)(((mem_ptr_t)(addr) + MEM_ALIGNMENT - 1) & ~(mem_ptr_t)(MEM_ALIGNMENT-1)))
#endif
#ifdef __cplusplus
}
#endif

View File

@ -48,12 +48,6 @@
// 32-bit alignment
#define MEM_ALIGNMENT 4
#if defined(TARGET_LPC4088)
#define MEM_SIZE 15360
#else
#define MEM_SIZE 16362
#endif
#define PBUF_POOL_SIZE 5
#define MEMP_NUM_TCP_PCB_LISTEN 4
#define MEMP_NUM_TCP_PCB 4

View File

@ -214,9 +214,12 @@ osThreadDef_t os_thread_def_main = {(os_pthread)main, osPriorityNormal, 0, NULL}
#elif defined(TARGET_LPC812)
#define INITIAL_SP (0x10001000UL)
#elif defined(TARGET_KL25Z) || defined(TARGET_K64F)
#elif defined(TARGET_KL25Z)
#define INITIAL_SP (0x20003000UL)
#elif defined(TARGET_K64F)
#define INITIAL_SP (0x20030000UL)
#elif defined(TARGET_KL46Z)
#define INITIAL_SP (0x20006000UL)

View File

@ -171,7 +171,7 @@ class K64F(Target):
self.extra_labels = ['Freescale', 'KPSDK_MCUS', 'KPSDK_CODE']
self.macros = ["CPU_MK64FN1M0VMD12"]
self.macros = ["CPU_MK64FN1M0VMD12", "FSL_RTOS_MBED"]
self.supported_toolchains = ["ARM"]