mirror of https://github.com/ARMmbed/mbed-os.git
Added K64F TCP/IP support
Currently NET_7 (HttpClient test) and NET_8 (NTP test) fail for unknown reasons.pull/274/head
parent
bbfdef0fac
commit
9a5f81d75c
|
@ -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
|
||||
******************************************************************************/
|
||||
|
|
@ -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
|
||||
******************************************************************************/
|
||||
|
|
@ -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
|
||||
******************************************************************************/
|
||||
|
|
@ -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
|
||||
******************************************************************************/
|
||||
|
|
@ -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)
|
|
@ -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
|
||||
******************************************************************************/
|
||||
|
|
@ -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
|
||||
******************************************************************************/
|
||||
|
|
@ -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
|
||||
******************************************************************************/
|
||||
|
|
@ -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)
|
||||
|
|
@ -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
|
||||
******************************************************************************/
|
||||
|
|
@ -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
|
||||
******************************************************************************/
|
||||
|
|
@ -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
|
||||
******************************************************************************/
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
PIT_DRIVER_DIR := $(SDK_ROOT)/platform/drivers/pit
|
||||
SOURCES += $(wildcard $(PIT_DRIVER_DIR)/src/*.c)
|
||||
INCLUDES += $(PIT_DRIVER_DIR)
|
|
@ -31,11 +31,16 @@
|
|||
#define __FSL_ENET_FEATURES_H__
|
||||
|
||||
|
||||
#if defined(CPU_MK63FN1M0VMD12) || defined(CPU_MK63FN1M0VMD12WS) || defined(CPU_MK64FN1M0VMD12) || defined(CPU_MK64FX512VMD12)
|
||||
#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_SUPPORT_PTP (0)
|
||||
|
|
|
@ -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
|
||||
******************************************************************************/
|
||||
|
|
@ -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_
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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
|
||||
******************************************************************************/
|
||||
|
|
@ -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
|
||||
******************************************************************************/
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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_
|
||||
|
|
@ -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
|
||||
******************************************************************************/
|
||||
|
|
@ -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
|
||||
******************************************************************************/
|
||||
|
|
@ -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 ------------------------------ */
|
||||
|
|
@ -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__
|
||||
|
|
@ -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
|
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
|
@ -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
|
|
@ -21,4 +21,10 @@
|
|||
|
||||
#define LWIP_TRANSPORT_ETHERNET 1
|
||||
|
||||
#if defined(TARGET_LPC4088)
|
||||
#define MEM_SIZE 15360
|
||||
#elif defined(TARGET_LPC1768)
|
||||
#define MEM_SIZE 16362
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -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 */
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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"]
|
||||
|
||||
|
|
Loading…
Reference in New Issue