From 9a5f81d75c0f409f45c5dd0cdd0026af4a6dfdc4 Mon Sep 17 00:00:00 2001 From: Bogdan Marinescu Date: Wed, 23 Apr 2014 16:11:07 +0100 Subject: [PATCH] Added K64F TCP/IP support Currently NET_7 (HttpClient test) and NET_8 (NTP test) fail for unknown reasons. --- .../common/phyksz8081/fsl_phy_driver.c | 264 +++++ .../common/phyksz8081/fsl_phy_driver.h | 190 ++++ .../drivers/enet/fsl_enet_driver.h | 947 ++++++++++++++++++ .../drivers/enet/src/fsl_enet_irq.c | 106 ++ .../TARGET_KPSDK_CODE/drivers/enet/subdir.mk | 4 + .../interrupt/fsl_interrupt_features.h | 59 ++ .../drivers/interrupt/fsl_interrupt_manager.h | 142 +++ .../interrupt/src/fsl_interrupt_manager.c | 109 ++ .../drivers/interrupt/subdir.mk | 4 + .../drivers/pit/fsl_pit_driver.h | 240 +++++ .../drivers/pit/src/fsl_pit_driver.c | 242 +++++ .../drivers/pit/src/fsl_pit_irq.c | 169 ++++ .../TARGET_KPSDK_CODE/drivers/pit/subdir.mk | 3 + .../hal/enet/fsl_enet_features.h | 11 +- .../utilities/fsl_os_abstraction.h | 569 +++++++++++ .../utilities/fsl_os_abstraction_mbed.h | 38 + .../utilities/src/fsl_os_abstraction_mbed.c | 35 + .../utilities/src/sw_timer.c | 311 ++++++ .../TARGET_KPSDK_CODE/utilities/sw_timer.h | 191 ++++ .../EthernetInterface/EthernetInterface.cpp | 32 +- .../eth/EthernetInterface/EthernetInterface.h | 4 +- .../net/eth/EthernetInterface/eth_arch.h | 41 + .../arch/TARGET_K64F/fsl_enet_driver.c | 455 +++++++++ .../arch/TARGET_K64F/hardware_init_MK64F12.c | 92 ++ .../eth/lwip-eth/arch/TARGET_K64F/k64f_emac.c | 864 ++++++++++++++++ .../arch/TARGET_K64F/k64f_emac_config.h | 47 + .../lwip-eth/arch/TARGET_K64F/lwipopts_conf.h | 29 + .../arch/{ => TARGET_NXP}/lpc17_emac.c | 99 +- .../arch/{ => TARGET_NXP}/lpc17xx_emac.h | 0 .../arch/{ => TARGET_NXP}/lpc_emac_config.h | 0 .../lwip-eth/arch/{ => TARGET_NXP}/lpc_phy.h | 0 .../arch/{ => TARGET_NXP}/lpc_phy_dp83848.c | 89 ++ .../arch/TARGET_NXP}/lwipopts_conf.h | 8 +- libraries/net/eth/lwip-eth/arch/lpc17_emac.h | 51 - libraries/net/lwip/lwip/core/mem.c | 10 +- libraries/net/lwip/lwip/core/memp.c | 2 +- libraries/net/lwip/lwip/include/lwip/mem.h | 1 + libraries/net/lwip/lwip/lwipopts.h | 6 - libraries/rtos/rtx/RTX_CM_lib.h | 5 +- workspace_tools/targets.py | 2 +- 40 files changed, 5296 insertions(+), 175 deletions(-) create mode 100644 libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KPSDK_MCUS/TARGET_KPSDK_CODE/common/phyksz8081/fsl_phy_driver.c create mode 100644 libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KPSDK_MCUS/TARGET_KPSDK_CODE/common/phyksz8081/fsl_phy_driver.h create mode 100644 libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KPSDK_MCUS/TARGET_KPSDK_CODE/drivers/enet/fsl_enet_driver.h create mode 100644 libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KPSDK_MCUS/TARGET_KPSDK_CODE/drivers/enet/src/fsl_enet_irq.c create mode 100644 libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KPSDK_MCUS/TARGET_KPSDK_CODE/drivers/enet/subdir.mk create mode 100644 libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KPSDK_MCUS/TARGET_KPSDK_CODE/drivers/interrupt/fsl_interrupt_features.h create mode 100644 libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KPSDK_MCUS/TARGET_KPSDK_CODE/drivers/interrupt/fsl_interrupt_manager.h create mode 100644 libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KPSDK_MCUS/TARGET_KPSDK_CODE/drivers/interrupt/src/fsl_interrupt_manager.c create mode 100644 libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KPSDK_MCUS/TARGET_KPSDK_CODE/drivers/interrupt/subdir.mk create mode 100644 libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KPSDK_MCUS/TARGET_KPSDK_CODE/drivers/pit/fsl_pit_driver.h create mode 100644 libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KPSDK_MCUS/TARGET_KPSDK_CODE/drivers/pit/src/fsl_pit_driver.c create mode 100644 libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KPSDK_MCUS/TARGET_KPSDK_CODE/drivers/pit/src/fsl_pit_irq.c create mode 100644 libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KPSDK_MCUS/TARGET_KPSDK_CODE/drivers/pit/subdir.mk create mode 100644 libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KPSDK_MCUS/TARGET_KPSDK_CODE/utilities/fsl_os_abstraction.h create mode 100644 libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KPSDK_MCUS/TARGET_KPSDK_CODE/utilities/fsl_os_abstraction_mbed.h create mode 100644 libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KPSDK_MCUS/TARGET_KPSDK_CODE/utilities/src/fsl_os_abstraction_mbed.c create mode 100644 libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KPSDK_MCUS/TARGET_KPSDK_CODE/utilities/src/sw_timer.c create mode 100644 libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KPSDK_MCUS/TARGET_KPSDK_CODE/utilities/sw_timer.h create mode 100644 libraries/net/eth/EthernetInterface/eth_arch.h create mode 100644 libraries/net/eth/lwip-eth/arch/TARGET_K64F/fsl_enet_driver.c create mode 100644 libraries/net/eth/lwip-eth/arch/TARGET_K64F/hardware_init_MK64F12.c create mode 100644 libraries/net/eth/lwip-eth/arch/TARGET_K64F/k64f_emac.c create mode 100644 libraries/net/eth/lwip-eth/arch/TARGET_K64F/k64f_emac_config.h create mode 100644 libraries/net/eth/lwip-eth/arch/TARGET_K64F/lwipopts_conf.h rename libraries/net/eth/lwip-eth/arch/{ => TARGET_NXP}/lpc17_emac.c (94%) rename libraries/net/eth/lwip-eth/arch/{ => TARGET_NXP}/lpc17xx_emac.h (100%) rename libraries/net/eth/lwip-eth/arch/{ => TARGET_NXP}/lpc_emac_config.h (100%) rename libraries/net/eth/lwip-eth/arch/{ => TARGET_NXP}/lpc_phy.h (100%) rename libraries/net/eth/lwip-eth/arch/{ => TARGET_NXP}/lpc_phy_dp83848.c (86%) rename libraries/net/eth/{EthernetInterface => lwip-eth/arch/TARGET_NXP}/lwipopts_conf.h (85%) delete mode 100644 libraries/net/eth/lwip-eth/arch/lpc17_emac.h diff --git a/libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KPSDK_MCUS/TARGET_KPSDK_CODE/common/phyksz8081/fsl_phy_driver.c b/libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KPSDK_MCUS/TARGET_KPSDK_CODE/common/phyksz8081/fsl_phy_driver.c new file mode 100644 index 0000000000..2982c0fa9f --- /dev/null +++ b/libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KPSDK_MCUS/TARGET_KPSDK_CODE/common/phyksz8081/fsl_phy_driver.c @@ -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 + ******************************************************************************/ + diff --git a/libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KPSDK_MCUS/TARGET_KPSDK_CODE/common/phyksz8081/fsl_phy_driver.h b/libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KPSDK_MCUS/TARGET_KPSDK_CODE/common/phyksz8081/fsl_phy_driver.h new file mode 100644 index 0000000000..23b4a6a1b6 --- /dev/null +++ b/libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KPSDK_MCUS/TARGET_KPSDK_CODE/common/phyksz8081/fsl_phy_driver.h @@ -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 +#include +#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 + ******************************************************************************/ + diff --git a/libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KPSDK_MCUS/TARGET_KPSDK_CODE/drivers/enet/fsl_enet_driver.h b/libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KPSDK_MCUS/TARGET_KPSDK_CODE/drivers/enet/fsl_enet_driver.h new file mode 100644 index 0000000000..c975d2a05f --- /dev/null +++ b/libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KPSDK_MCUS/TARGET_KPSDK_CODE/drivers/enet/fsl_enet_driver.h @@ -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 +#include +#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 + ******************************************************************************/ + diff --git a/libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KPSDK_MCUS/TARGET_KPSDK_CODE/drivers/enet/src/fsl_enet_irq.c b/libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KPSDK_MCUS/TARGET_KPSDK_CODE/drivers/enet/src/fsl_enet_irq.c new file mode 100644 index 0000000000..c7f5db2eaf --- /dev/null +++ b/libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KPSDK_MCUS/TARGET_KPSDK_CODE/drivers/enet/src/fsl_enet_irq.c @@ -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 + ******************************************************************************/ + diff --git a/libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KPSDK_MCUS/TARGET_KPSDK_CODE/drivers/enet/subdir.mk b/libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KPSDK_MCUS/TARGET_KPSDK_CODE/drivers/enet/subdir.mk new file mode 100644 index 0000000000..533824b7cd --- /dev/null +++ b/libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KPSDK_MCUS/TARGET_KPSDK_CODE/drivers/enet/subdir.mk @@ -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) diff --git a/libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KPSDK_MCUS/TARGET_KPSDK_CODE/drivers/interrupt/fsl_interrupt_features.h b/libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KPSDK_MCUS/TARGET_KPSDK_CODE/drivers/interrupt/fsl_interrupt_features.h new file mode 100644 index 0000000000..660818e55a --- /dev/null +++ b/libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KPSDK_MCUS/TARGET_KPSDK_CODE/drivers/interrupt/fsl_interrupt_features.h @@ -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 + ******************************************************************************/ + diff --git a/libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KPSDK_MCUS/TARGET_KPSDK_CODE/drivers/interrupt/fsl_interrupt_manager.h b/libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KPSDK_MCUS/TARGET_KPSDK_CODE/drivers/interrupt/fsl_interrupt_manager.h new file mode 100644 index 0000000000..6866ba195f --- /dev/null +++ b/libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KPSDK_MCUS/TARGET_KPSDK_CODE/drivers/interrupt/fsl_interrupt_manager.h @@ -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 +#include +#include +#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 + ******************************************************************************/ + diff --git a/libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KPSDK_MCUS/TARGET_KPSDK_CODE/drivers/interrupt/src/fsl_interrupt_manager.c b/libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KPSDK_MCUS/TARGET_KPSDK_CODE/drivers/interrupt/src/fsl_interrupt_manager.c new file mode 100644 index 0000000000..51a006bc9e --- /dev/null +++ b/libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KPSDK_MCUS/TARGET_KPSDK_CODE/drivers/interrupt/src/fsl_interrupt_manager.c @@ -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 +#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 + ******************************************************************************/ + diff --git a/libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KPSDK_MCUS/TARGET_KPSDK_CODE/drivers/interrupt/subdir.mk b/libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KPSDK_MCUS/TARGET_KPSDK_CODE/drivers/interrupt/subdir.mk new file mode 100644 index 0000000000..d4f661c806 --- /dev/null +++ b/libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KPSDK_MCUS/TARGET_KPSDK_CODE/drivers/interrupt/subdir.mk @@ -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) + diff --git a/libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KPSDK_MCUS/TARGET_KPSDK_CODE/drivers/pit/fsl_pit_driver.h b/libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KPSDK_MCUS/TARGET_KPSDK_CODE/drivers/pit/fsl_pit_driver.h new file mode 100644 index 0000000000..5d8f5ba468 --- /dev/null +++ b/libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KPSDK_MCUS/TARGET_KPSDK_CODE/drivers/pit/fsl_pit_driver.h @@ -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 +#include +#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 + ******************************************************************************/ + diff --git a/libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KPSDK_MCUS/TARGET_KPSDK_CODE/drivers/pit/src/fsl_pit_driver.c b/libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KPSDK_MCUS/TARGET_KPSDK_CODE/drivers/pit/src/fsl_pit_driver.c new file mode 100644 index 0000000000..58a7feada6 --- /dev/null +++ b/libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KPSDK_MCUS/TARGET_KPSDK_CODE/drivers/pit/src/fsl_pit_driver.c @@ -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 + ******************************************************************************/ + diff --git a/libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KPSDK_MCUS/TARGET_KPSDK_CODE/drivers/pit/src/fsl_pit_irq.c b/libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KPSDK_MCUS/TARGET_KPSDK_CODE/drivers/pit/src/fsl_pit_irq.c new file mode 100644 index 0000000000..b6baba8baa --- /dev/null +++ b/libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KPSDK_MCUS/TARGET_KPSDK_CODE/drivers/pit/src/fsl_pit_irq.c @@ -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 +#include +#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 + ******************************************************************************/ + diff --git a/libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KPSDK_MCUS/TARGET_KPSDK_CODE/drivers/pit/subdir.mk b/libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KPSDK_MCUS/TARGET_KPSDK_CODE/drivers/pit/subdir.mk new file mode 100644 index 0000000000..fbde3e5f92 --- /dev/null +++ b/libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KPSDK_MCUS/TARGET_KPSDK_CODE/drivers/pit/subdir.mk @@ -0,0 +1,3 @@ +PIT_DRIVER_DIR := $(SDK_ROOT)/platform/drivers/pit +SOURCES += $(wildcard $(PIT_DRIVER_DIR)/src/*.c) +INCLUDES += $(PIT_DRIVER_DIR) diff --git a/libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KPSDK_MCUS/TARGET_KPSDK_CODE/hal/enet/fsl_enet_features.h b/libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KPSDK_MCUS/TARGET_KPSDK_CODE/hal/enet/fsl_enet_features.h index e8e603cf29..c9b9f04345 100644 --- a/libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KPSDK_MCUS/TARGET_KPSDK_CODE/hal/enet/fsl_enet_features.h +++ b/libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KPSDK_MCUS/TARGET_KPSDK_CODE/hal/enet/fsl_enet_features.h @@ -31,13 +31,18 @@ #define __FSL_ENET_FEATURES_H__ -#if defined(CPU_MK63FN1M0VMD12) || defined(CPU_MK63FN1M0VMD12WS) || defined(CPU_MK64FN1M0VMD12) || defined(CPU_MK64FX512VMD12) - #define FSL_FEATURE_ENET_DMA_BIG_ENDIAN_ONLY (1) +#if defined(CPU_MK63FN1M0VMD12) || defined(CPU_MK63FN1M0VMD12WS) + #define FSL_FEATURE_ENET_DMA_BIG_ENDIAN_ONLY (1) + #define FSL_FEATURE_ENET_SUPPORT_PTP (0) + #define FSL_FEATURE_ENET_INTERRUPT_COUNT (4) + #define FSL_FEATURE_ENET_PTP_TIMER_CHANNEL_INTERRUPT (0) +#elif defined(CPU_MK64FN1M0VMD12) || defined(CPU_MK64FX512VMD12) + #define FSL_FEATURE_ENET_DMA_BIG_ENDIAN_ONLY (0) #define FSL_FEATURE_ENET_SUPPORT_PTP (0) #define FSL_FEATURE_ENET_INTERRUPT_COUNT (4) #define FSL_FEATURE_ENET_PTP_TIMER_CHANNEL_INTERRUPT (0) #elif defined(CPU_MK70FN1M0VMJ12) - #define FSL_FEATURE_ENET_DMA_BIG_ENDIAN_ONLY (1) + #define FSL_FEATURE_ENET_DMA_BIG_ENDIAN_ONLY (1) #define FSL_FEATURE_ENET_SUPPORT_PTP (0) #define FSL_FEATURE_ENET_INTERRUPT_COUNT (4) #else diff --git a/libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KPSDK_MCUS/TARGET_KPSDK_CODE/utilities/fsl_os_abstraction.h b/libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KPSDK_MCUS/TARGET_KPSDK_CODE/utilities/fsl_os_abstraction.h new file mode 100644 index 0000000000..1021402ef6 --- /dev/null +++ b/libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KPSDK_MCUS/TARGET_KPSDK_CODE/utilities/fsl_os_abstraction.h @@ -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 +#include +#include + +#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 + ******************************************************************************/ + diff --git a/libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KPSDK_MCUS/TARGET_KPSDK_CODE/utilities/fsl_os_abstraction_mbed.h b/libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KPSDK_MCUS/TARGET_KPSDK_CODE/utilities/fsl_os_abstraction_mbed.h new file mode 100644 index 0000000000..ac7669c5e8 --- /dev/null +++ b/libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KPSDK_MCUS/TARGET_KPSDK_CODE/utilities/fsl_os_abstraction_mbed.h @@ -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_ diff --git a/libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KPSDK_MCUS/TARGET_KPSDK_CODE/utilities/src/fsl_os_abstraction_mbed.c b/libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KPSDK_MCUS/TARGET_KPSDK_CODE/utilities/src/fsl_os_abstraction_mbed.c new file mode 100644 index 0000000000..47849f4044 --- /dev/null +++ b/libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KPSDK_MCUS/TARGET_KPSDK_CODE/utilities/src/fsl_os_abstraction_mbed.c @@ -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); +} + diff --git a/libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KPSDK_MCUS/TARGET_KPSDK_CODE/utilities/src/sw_timer.c b/libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KPSDK_MCUS/TARGET_KPSDK_CODE/utilities/src/sw_timer.c new file mode 100644 index 0000000000..9b6b69cf6c --- /dev/null +++ b/libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KPSDK_MCUS/TARGET_KPSDK_CODE/utilities/src/sw_timer.c @@ -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 + ******************************************************************************/ + diff --git a/libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KPSDK_MCUS/TARGET_KPSDK_CODE/utilities/sw_timer.h b/libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KPSDK_MCUS/TARGET_KPSDK_CODE/utilities/sw_timer.h new file mode 100644 index 0000000000..fbd4660517 --- /dev/null +++ b/libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KPSDK_MCUS/TARGET_KPSDK_CODE/utilities/sw_timer.h @@ -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 +#include + +/*! @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 + ******************************************************************************/ + diff --git a/libraries/net/eth/EthernetInterface/EthernetInterface.cpp b/libraries/net/eth/EthernetInterface/EthernetInterface.cpp index 16c1a9704e..73ce896bb8 100644 --- a/libraries/net/eth/EthernetInterface/EthernetInterface.cpp +++ b/libraries/net/eth/EthernetInterface/EthernetInterface.cpp @@ -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; } diff --git a/libraries/net/eth/EthernetInterface/EthernetInterface.h b/libraries/net/eth/EthernetInterface/EthernetInterface.h index 3b9336e5a6..632072dbf8 100644 --- a/libraries/net/eth/EthernetInterface/EthernetInterface.h +++ b/libraries/net/eth/EthernetInterface/EthernetInterface.h @@ -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" diff --git a/libraries/net/eth/EthernetInterface/eth_arch.h b/libraries/net/eth/EthernetInterface/eth_arch.h new file mode 100644 index 0000000000..1ff54b1d38 --- /dev/null +++ b/libraries/net/eth/EthernetInterface/eth_arch.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_ + diff --git a/libraries/net/eth/lwip-eth/arch/TARGET_K64F/fsl_enet_driver.c b/libraries/net/eth/lwip-eth/arch/TARGET_K64F/fsl_enet_driver.c new file mode 100644 index 0000000000..f7fe320506 --- /dev/null +++ b/libraries/net/eth/lwip-eth/arch/TARGET_K64F/fsl_enet_driver.c @@ -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 + +#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 + ******************************************************************************/ + diff --git a/libraries/net/eth/lwip-eth/arch/TARGET_K64F/hardware_init_MK64F12.c b/libraries/net/eth/lwip-eth/arch/TARGET_K64F/hardware_init_MK64F12.c new file mode 100644 index 0000000000..22f3af0f60 --- /dev/null +++ b/libraries/net/eth/lwip-eth/arch/TARGET_K64F/hardware_init_MK64F12.c @@ -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 + ******************************************************************************/ + diff --git a/libraries/net/eth/lwip-eth/arch/TARGET_K64F/k64f_emac.c b/libraries/net/eth/lwip-eth/arch/TARGET_K64F/k64f_emac.c new file mode 100644 index 0000000000..b4d252518b --- /dev/null +++ b/libraries/net/eth/lwip-eth/arch/TARGET_K64F/k64f_emac.c @@ -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 +#include +#include +#include + +#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 ------------------------------ */ + diff --git a/libraries/net/eth/lwip-eth/arch/TARGET_K64F/k64f_emac_config.h b/libraries/net/eth/lwip-eth/arch/TARGET_K64F/k64f_emac_config.h new file mode 100644 index 0000000000..82b65ac0d8 --- /dev/null +++ b/libraries/net/eth/lwip-eth/arch/TARGET_K64F/k64f_emac_config.h @@ -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__ + diff --git a/libraries/net/eth/lwip-eth/arch/TARGET_K64F/lwipopts_conf.h b/libraries/net/eth/lwip-eth/arch/TARGET_K64F/lwipopts_conf.h new file mode 100644 index 0000000000..4b135c6f13 --- /dev/null +++ b/libraries/net/eth/lwip-eth/arch/TARGET_K64F/lwipopts_conf.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 diff --git a/libraries/net/eth/lwip-eth/arch/lpc17_emac.c b/libraries/net/eth/lwip-eth/arch/TARGET_NXP/lpc17_emac.c similarity index 94% rename from libraries/net/eth/lwip-eth/arch/lpc17_emac.c rename to libraries/net/eth/lwip-eth/arch/TARGET_NXP/lpc17_emac.c index 729840f636..aa6d19d470 100644 --- a/libraries/net/eth/lwip-eth/arch/lpc17_emac.c +++ b/libraries/net/eth/lwip-eth/arch/TARGET_NXP/lpc17_emac.c @@ -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); +} + /** * @} */ diff --git a/libraries/net/eth/lwip-eth/arch/lpc17xx_emac.h b/libraries/net/eth/lwip-eth/arch/TARGET_NXP/lpc17xx_emac.h similarity index 100% rename from libraries/net/eth/lwip-eth/arch/lpc17xx_emac.h rename to libraries/net/eth/lwip-eth/arch/TARGET_NXP/lpc17xx_emac.h diff --git a/libraries/net/eth/lwip-eth/arch/lpc_emac_config.h b/libraries/net/eth/lwip-eth/arch/TARGET_NXP/lpc_emac_config.h similarity index 100% rename from libraries/net/eth/lwip-eth/arch/lpc_emac_config.h rename to libraries/net/eth/lwip-eth/arch/TARGET_NXP/lpc_emac_config.h diff --git a/libraries/net/eth/lwip-eth/arch/lpc_phy.h b/libraries/net/eth/lwip-eth/arch/TARGET_NXP/lpc_phy.h similarity index 100% rename from libraries/net/eth/lwip-eth/arch/lpc_phy.h rename to libraries/net/eth/lwip-eth/arch/TARGET_NXP/lpc_phy.h diff --git a/libraries/net/eth/lwip-eth/arch/lpc_phy_dp83848.c b/libraries/net/eth/lwip-eth/arch/TARGET_NXP/lpc_phy_dp83848.c similarity index 86% rename from libraries/net/eth/lwip-eth/arch/lpc_phy_dp83848.c rename to libraries/net/eth/lwip-eth/arch/TARGET_NXP/lpc_phy_dp83848.c index eca6d97338..14813a561b 100644 --- a/libraries/net/eth/lwip-eth/arch/lpc_phy_dp83848.c +++ b/libraries/net/eth/lwip-eth/arch/TARGET_NXP/lpc_phy_dp83848.c @@ -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 diff --git a/libraries/net/eth/EthernetInterface/lwipopts_conf.h b/libraries/net/eth/lwip-eth/arch/TARGET_NXP/lwipopts_conf.h similarity index 85% rename from libraries/net/eth/EthernetInterface/lwipopts_conf.h rename to libraries/net/eth/lwip-eth/arch/TARGET_NXP/lwipopts_conf.h index bfbb1d8235..7be78dc724 100644 --- a/libraries/net/eth/EthernetInterface/lwipopts_conf.h +++ b/libraries/net/eth/lwip-eth/arch/TARGET_NXP/lwipopts_conf.h @@ -19,6 +19,12 @@ #ifndef LWIPOPTS_CONF_H #define LWIPOPTS_CONF_H -#define LWIP_TRANSPORT_ETHERNET 1 +#define LWIP_TRANSPORT_ETHERNET 1 + +#if defined(TARGET_LPC4088) +#define MEM_SIZE 15360 +#elif defined(TARGET_LPC1768) +#define MEM_SIZE 16362 +#endif #endif diff --git a/libraries/net/eth/lwip-eth/arch/lpc17_emac.h b/libraries/net/eth/lwip-eth/arch/lpc17_emac.h deleted file mode 100644 index 851030ddb2..0000000000 --- a/libraries/net/eth/lwip-eth/arch/lpc17_emac.h +++ /dev/null @@ -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 */ diff --git a/libraries/net/lwip/lwip/core/mem.c b/libraries/net/lwip/lwip/core/mem.c index 6d2c4f909b..580fc7759f 100644 --- a/libraries/net/lwip/lwip/core/mem.c +++ b/libraries/net/lwip/lwip/core/mem.c @@ -186,8 +186,10 @@ struct mem { # else # define ETHMEM_SECTION __attribute__((section("AHBSRAM1"),aligned)) # endif -#else +#elif defined(TARGET_LPC1768) # define ETHMEM_SECTION __attribute((section("AHBSRAM0"))) +#else +# define ETHMEM_SECTION #endif /** the heap. we need one struct mem at the end and some room for alignment */ @@ -609,10 +611,10 @@ mem_malloc(mem_size_t size) sys_mutex_unlock(&mem_mutex); LWIP_ASSERT("mem_malloc: allocated memory not above ram_end.", (mem_ptr_t)mem + SIZEOF_STRUCT_MEM + size <= (mem_ptr_t)ram_end); - LWIP_ASSERT("mem_malloc: allocated memory properly aligned.", - ((mem_ptr_t)mem + SIZEOF_STRUCT_MEM) % MEM_ALIGNMENT == 0); + LWIP_ASSERT("mem_malloc: allocated memory properly aligned.", + ((mem_ptr_t)mem + SIZEOF_STRUCT_MEM) % MEM_ALIGNMENT == 0); LWIP_ASSERT("mem_malloc: sanity check alignment", - (((mem_ptr_t)mem) & (MEM_ALIGNMENT-1)) == 0); + (((mem_ptr_t)mem) & (MEM_ALIGNMENT-1)) == 0); return (u8_t *)mem + SIZEOF_STRUCT_MEM; } diff --git a/libraries/net/lwip/lwip/core/memp.c b/libraries/net/lwip/lwip/core/memp.c index 19bc5579db..dc5ae51d46 100644 --- a/libraries/net/lwip/lwip/core/memp.c +++ b/libraries/net/lwip/lwip/core/memp.c @@ -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 diff --git a/libraries/net/lwip/lwip/include/lwip/mem.h b/libraries/net/lwip/lwip/include/lwip/mem.h index 9507c0aec4..f4b2f7c010 100644 --- a/libraries/net/lwip/lwip/include/lwip/mem.h +++ b/libraries/net/lwip/lwip/include/lwip/mem.h @@ -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 diff --git a/libraries/net/lwip/lwip/lwipopts.h b/libraries/net/lwip/lwip/lwipopts.h index b2f5d7f72e..1d68e59937 100644 --- a/libraries/net/lwip/lwip/lwipopts.h +++ b/libraries/net/lwip/lwip/lwipopts.h @@ -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 diff --git a/libraries/rtos/rtx/RTX_CM_lib.h b/libraries/rtos/rtx/RTX_CM_lib.h index e9fdda43a6..eb96bf4006 100644 --- a/libraries/rtos/rtx/RTX_CM_lib.h +++ b/libraries/rtos/rtx/RTX_CM_lib.h @@ -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) diff --git a/workspace_tools/targets.py b/workspace_tools/targets.py index 44aff608d3..d769763fc7 100644 --- a/workspace_tools/targets.py +++ b/workspace_tools/targets.py @@ -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"]