From f4d86cec7fb847b98b305adf4efdb3f8157f0c9b Mon Sep 17 00:00:00 2001 From: Wayne Lin Date: Wed, 2 Sep 2020 17:49:17 +0800 Subject: Fix USB host core issues. 1. Limit >4 USB ports hubs. 2. Double free intf. 3. dname buffer size is too small. 4. Reset child pointer after detaching instance. --- components/drivers/usb/usbhost/class/udisk.c | 2 +- components/drivers/usb/usbhost/core/hub.c | 15 ++++++++++++--- 2 files changed, 13 insertions(+), 4 deletions(-) (limited to 'components') diff --git a/components/drivers/usb/usbhost/class/udisk.c b/components/drivers/usb/usbhost/class/udisk.c index 1509a26105..6c8030b29a 100644 --- a/components/drivers/usb/usbhost/class/udisk.c +++ b/components/drivers/usb/usbhost/class/udisk.c @@ -186,7 +186,7 @@ rt_err_t rt_udisk_run(struct uhintf* intf) { int i = 0; rt_err_t ret; - char dname[4]; + char dname[8]; char sname[8]; rt_uint8_t max_lun, *sector, sense[18], inquiry[36]; struct dfs_partition part[MAX_PARTITION_COUNT]; diff --git a/components/drivers/usb/usbhost/core/hub.c b/components/drivers/usb/usbhost/core/hub.c index fb6cd9c406..eefa571472 100644 --- a/components/drivers/usb/usbhost/core/hub.c +++ b/components/drivers/usb/usbhost/core/hub.c @@ -417,8 +417,13 @@ static rt_err_t rt_usbh_hub_port_change(uhub_t hub) if(reconnect) { - if(hub->child[i] != RT_NULL && hub->child[i]->status != DEV_STATUS_IDLE) + if(hub->child[i] != RT_NULL && hub->child[i]->status != DEV_STATUS_IDLE) + { rt_usbh_detach_instance(hub->child[i]); + + /* Child device have been detach. Set hub->child[i] to NULL. */ + hub->child[i] = RT_NULL; + } ret = rt_usbh_hub_port_debounce(hub, i + 1); if(ret != RT_EOK) continue; @@ -532,7 +537,12 @@ static rt_err_t rt_usbh_hub_enable(void *arg) } /* get hub ports number */ - hub->num_ports = hub->hub_desc.num_ports; + /* If hub device supported ports over USB_HUB_PORT_NUM(Ex: 8 port hub). Set hub->num_ports to USB_HUB_PORT_NUM */ + if(hub->hub_desc.num_ports > USB_HUB_PORT_NUM) + hub->num_ports = USB_HUB_PORT_NUM; + else + hub->num_ports = hub->hub_desc.num_ports; + hub->hcd = device->hcd; hub->self = device; @@ -607,7 +617,6 @@ static rt_err_t rt_usbh_hub_disable(void* arg) } if(hub != RT_NULL) rt_free(hub); - if(intf != RT_NULL) rt_free(intf); return RT_EOK; } -- cgit v1.3.1 From 502378cf93bf780035316d594c80dd9b027efa17 Mon Sep 17 00:00:00 2001 From: WangQiang Date: Mon, 12 Oct 2020 18:15:01 +0800 Subject: 1. 抽象了PHY的设备模型,在components中增加了PHY设备的相关代码以及KCONFIG配置和SConscript脚本 2. 在IMXRT的Libraries中增加了peripherals目录,用于具体型号的设备驱动相关的代码的实现,不应与MCU的平台相关,实现PHY的设备对象中的相关接口。 3. 修改了BSP中的Sconstruct文件,增加了peripherals目录的构建 4. 修改了KEIL环境的SCT文件,用于实现以太网功能 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bsp/imxrt/imxrt1064-nxp-evk/SConstruct | 3 + bsp/imxrt/imxrt1064-nxp-evk/board/Kconfig | 35 +- bsp/imxrt/imxrt1064-nxp-evk/board/SConscript | 4 - bsp/imxrt/imxrt1064-nxp-evk/board/board.c | 26 ++ bsp/imxrt/imxrt1064-nxp-evk/board/board.h | 2 +- .../board/linker_scripts/link.sct | 4 +- .../board/ports/phyksz8081/fsl_phy.c | 315 ------------------ .../board/ports/phyksz8081/fsl_phy.h | 200 ----------- bsp/imxrt/libraries/drivers/SConscript | 3 + bsp/imxrt/libraries/drivers/drv_eth.c | 94 +++--- bsp/imxrt/libraries/drivers/drv_mdio.c | 160 +++++++++ bsp/imxrt/libraries/drivers/drv_mdio.h | 25 ++ bsp/imxrt/libraries/peripherals/SConscript | 16 + bsp/imxrt/libraries/peripherals/phyksz8081.c | 367 +++++++++++++++++++++ bsp/imxrt/tools/sdk_dist.py | 3 + components/drivers/Kconfig | 4 + components/drivers/include/drivers/phy.h | 79 +++++ components/drivers/include/drivers/phy_mdio.h | 35 ++ components/drivers/include/rtdevice.h | 5 + components/drivers/phy/SConscript | 8 + components/drivers/phy/phy.c | 78 +++++ components/finsh/cmd.c | 1 + include/rtdef.h | 1 + 23 files changed, 903 insertions(+), 565 deletions(-) delete mode 100644 bsp/imxrt/imxrt1064-nxp-evk/board/ports/phyksz8081/fsl_phy.c delete mode 100644 bsp/imxrt/imxrt1064-nxp-evk/board/ports/phyksz8081/fsl_phy.h create mode 100644 bsp/imxrt/libraries/drivers/drv_mdio.c create mode 100644 bsp/imxrt/libraries/drivers/drv_mdio.h create mode 100644 bsp/imxrt/libraries/peripherals/SConscript create mode 100644 bsp/imxrt/libraries/peripherals/phyksz8081.c create mode 100644 components/drivers/include/drivers/phy.h create mode 100644 components/drivers/include/drivers/phy_mdio.h create mode 100644 components/drivers/phy/SConscript create mode 100644 components/drivers/phy/phy.c (limited to 'components') diff --git a/bsp/imxrt/imxrt1064-nxp-evk/SConstruct b/bsp/imxrt/imxrt1064-nxp-evk/SConstruct index 01c823f118..92ab729ed1 100644 --- a/bsp/imxrt/imxrt1064-nxp-evk/SConstruct +++ b/bsp/imxrt/imxrt1064-nxp-evk/SConstruct @@ -66,5 +66,8 @@ objs.extend(SConscript(os.path.join(libraries_path_prefix, imxrt_library, 'SCons # include drivers objs.extend(SConscript(os.path.join(libraries_path_prefix, 'drivers', 'SConscript'))) +# include peripherals +objs.extend(SConscript(os.path.join(libraries_path_prefix, 'peripherals', 'SConscript'))) + # make a building DoBuilding(TARGET, objs) diff --git a/bsp/imxrt/imxrt1064-nxp-evk/board/Kconfig b/bsp/imxrt/imxrt1064-nxp-evk/board/Kconfig index 4c7caa2d53..5c660b91c7 100644 --- a/bsp/imxrt/imxrt1064-nxp-evk/board/Kconfig +++ b/bsp/imxrt/imxrt1064-nxp-evk/board/Kconfig @@ -44,20 +44,41 @@ menu "Onboard Peripheral Drivers" menuconfig BSP_USING_ETH bool "Enable Ethernet" - select PHY_USING_KSZ8081 select RT_USING_NETDEV default n if BSP_USING_ETH - config PHY_USING_KSZ8081 - bool "i.MX RT1064EVK uses ksz8081 phy" + config BSP_USING_PHY + select RT_USING_PHY + bool "Enable ethernet phy" default y - config FSL_FEATURE_PHYKSZ8081_USE_RMII50M_MODE - bool "Enable the PHY ksz8081 RMII50M mode" - depends on PHY_USING_KSZ8081 - default y + if BSP_USING_PHY + config PHY_DEVICE_ADDRESS + int "Specify address of phy device" + default 2 + + config PHY_USING_KSZ8081 + bool "i.MX RT1064EVK uses ksz8081 phy" + default y + + if PHY_USING_KSZ8081 + config PHY_RESET_PORT + int "indicate port of reset" + default 1 + + config PHY_RESET_PIN + int "indicate pin of reset" + default 9 + + config FSL_FEATURE_PHYKSZ8081_USE_RMII50M_MODE + bool "Enable the PHY ksz8081 RMII50M mode" + depends on PHY_USING_KSZ8081 + default y + endif + + endif endif endmenu diff --git a/bsp/imxrt/imxrt1064-nxp-evk/board/SConscript b/bsp/imxrt/imxrt1064-nxp-evk/board/SConscript index 6afc7c3ae4..050a6c10bc 100644 --- a/bsp/imxrt/imxrt1064-nxp-evk/board/SConscript +++ b/bsp/imxrt/imxrt1064-nxp-evk/board/SConscript @@ -15,10 +15,6 @@ CPPPATH = [cwd,cwd + '/MCUX_Config',cwd + '/ports'] CPPDEFINES = ['CPU_MIMXRT1064DVL6A', 'SKIP_SYSCLK_INIT', 'EVK_MCIMXRM', 'FSL_SDK_ENABLE_DRIVER_CACHE_CONTROL=1','XIP_EXTERNAL_FLASH=1', 'XIP_BOOT_HEADER_ENABLE=1', 'XIP_BOOT_HEADER_DCD_ENABLE=1'] -if GetDepend(['PHY_USING_KSZ8081']): - src += Glob('ports/phyksz8081/fsl_phy.c') - CPPPATH += [cwd + '/ports/phyksz8081'] - if rtconfig.CROSS_TOOL == 'keil': CPPDEFINES.append('__FPU_PRESENT=1') diff --git a/bsp/imxrt/imxrt1064-nxp-evk/board/board.c b/bsp/imxrt/imxrt1064-nxp-evk/board/board.c index 0ef8769e0e..603cd856c5 100644 --- a/bsp/imxrt/imxrt1064-nxp-evk/board/board.c +++ b/bsp/imxrt/imxrt1064-nxp-evk/board/board.c @@ -416,6 +416,7 @@ void imxrt_enet_pins_init(void) Hyst. Enable Field: Hysteresis Disabled */ } +#ifndef BSP_USING_PHY void imxrt_enet_phy_reset_by_gpio(void) { gpio_pin_config_t gpio_config = {kGPIO_DigitalOutput, 0, kGPIO_NoIntmode}; @@ -428,8 +429,29 @@ void imxrt_enet_phy_reset_by_gpio(void) rt_thread_delay(100); GPIO_WritePinOutput(GPIO1, 9, 1); } +#endif /* BSP_USING_PHY */ + #endif /* BSP_USING_ETH */ +#ifdef BSP_USING_PHY +void imxrt_phy_pins_init( void ) +{ + IOMUXC_SetPinMux( + IOMUXC_GPIO_AD_B0_09_GPIO1_IO09, /* GPIO_AD_B0_09 is configured as GPIO1_IO09 */ + 0U); /* Software Input On Field: Input Path is determined by functionality */ + IOMUXC_SetPinConfig( + IOMUXC_GPIO_AD_B0_09_GPIO1_IO09, /* GPIO_B0_00 PAD functional properties : */ + 0x10B0u); /* Slew Rate Field: Slow Slew Rate + Drive Strength Field: R0/6 + Speed Field: medium(100MHz) + Open Drain Enable Field: Open Drain Disabled + Pull / Keep Enable Field: Pull/Keeper Enabled + Pull / Keep Select Field: Keeper + Pull Up / Down Config. Field: 100K Ohm Pull Down + Hyst. Enable Field: Hysteresis Disabled */ +} +#endif /* BSP_USING_PHY */ + /** * This function will initial rt1050 board. */ @@ -450,6 +472,10 @@ void rt_hw_board_init() imxrt_enet_pins_init(); #endif +#ifdef BSP_USING_PHY + imxrt_phy_pins_init(); +#endif + #ifdef BSP_USING_DMA imxrt_dma_init(); #endif diff --git a/bsp/imxrt/imxrt1064-nxp-evk/board/board.h b/bsp/imxrt/imxrt1064-nxp-evk/board/board.h index 500cc62450..dd7b7d3e56 100644 --- a/bsp/imxrt/imxrt1064-nxp-evk/board/board.h +++ b/bsp/imxrt/imxrt1064-nxp-evk/board/board.h @@ -48,7 +48,7 @@ void rt_hw_board_init(void); #ifdef BSP_USING_ETH void imxrt_enet_pins_init(void); void imxrt_enet_phy_reset_by_gpio(void); -#define PHY_ADDRESS 0x02u + #endif #endif diff --git a/bsp/imxrt/imxrt1064-nxp-evk/board/linker_scripts/link.sct b/bsp/imxrt/imxrt1064-nxp-evk/board/linker_scripts/link.sct index 7b7bf4fbba..f36201c200 100644 --- a/bsp/imxrt/imxrt1064-nxp-evk/board/linker_scripts/link.sct +++ b/bsp/imxrt/imxrt1064-nxp-evk/board/linker_scripts/link.sct @@ -66,6 +66,8 @@ #define m_data3_start 0x00000000 ; ITCM 128KB #define m_data3_size 0x00020000 +#define m_ncache_start 0x81E00000 +#define m_ncache_size 0x00200000 /* Sizes */ #if (defined(__stack_size__)) @@ -124,7 +126,7 @@ LR_IROM1 m_text_start m_text_size RTT_HEAP +0 EMPTY RTT_HEAP_SIZE{} ; ncache RW data - RW_m_ncache m_data2_start m_data2_size + RW_m_ncache m_ncache_start m_ncache_size { * (NonCacheable.init) * (NonCacheable) diff --git a/bsp/imxrt/imxrt1064-nxp-evk/board/ports/phyksz8081/fsl_phy.c b/bsp/imxrt/imxrt1064-nxp-evk/board/ports/phyksz8081/fsl_phy.c deleted file mode 100644 index 4197514aa5..0000000000 --- a/bsp/imxrt/imxrt1064-nxp-evk/board/ports/phyksz8081/fsl_phy.c +++ /dev/null @@ -1,315 +0,0 @@ -/* - * Copyright (c) 2015, Freescale Semiconductor, Inc. - * Copyright 2016-2017 NXP - * All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ - -#include "fsl_phy.h" -#include -/******************************************************************************* - * Definitions - ******************************************************************************/ - -/*! @brief Defines the timeout macro. */ -#define PHY_TIMEOUT_COUNT 0x3FFFFFFU - -/******************************************************************************* - * Prototypes - ******************************************************************************/ - -/*! - * @brief Get the ENET instance from peripheral base address. - * - * @param base ENET peripheral base address. - * @return ENET instance. - */ -extern uint32_t ENET_GetInstance(ENET_Type *base); - -/******************************************************************************* - * Variables - ******************************************************************************/ - -#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) -/*! @brief Pointers to enet clocks for each instance. */ -extern clock_ip_name_t s_enetClock[FSL_FEATURE_SOC_ENET_COUNT]; -#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ - -/******************************************************************************* - * Code - ******************************************************************************/ - -status_t PHY_Init(ENET_Type *base, uint32_t phyAddr, uint32_t srcClock_Hz) -{ - uint32_t bssReg; - uint32_t counter = PHY_TIMEOUT_COUNT; - uint32_t idReg = 0; - status_t result = kStatus_Success; - uint32_t instance = ENET_GetInstance(base); - uint32_t timeDelay; - uint32_t ctlReg = 0; - -#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) - /* Set SMI first. */ - CLOCK_EnableClock(s_enetClock[instance]); -#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ - ENET_SetSMI(base, srcClock_Hz, false); - - /* Initialization after PHY stars to work. */ - while ((idReg != PHY_CONTROL_ID1) && (counter != 0)) - { - PHY_Read(base, phyAddr, PHY_ID1_REG, &idReg); - counter --; - } - - if (!counter) - { - return kStatus_Fail; - } - - /* Reset PHY. */ - counter = PHY_TIMEOUT_COUNT; - result = PHY_Write(base, phyAddr, PHY_BASICCONTROL_REG, PHY_BCTL_RESET_MASK); - if (result == kStatus_Success) - { - -#if defined(FSL_FEATURE_PHYKSZ8081_USE_RMII50M_MODE) - uint32_t data = 0; - result = PHY_Read(base, phyAddr, PHY_CONTROL2_REG, &data); - if ( result != kStatus_Success) - { - return result; - } - result = PHY_Write(base, phyAddr, PHY_CONTROL2_REG, (data | PHY_CTL2_REFCLK_SELECT_MASK)); - if (result != kStatus_Success) - { - return result; - } -#endif /* FSL_FEATURE_PHYKSZ8081_USE_RMII50M_MODE */ - - /* Set the negotiation. */ - result = PHY_Write(base, phyAddr, PHY_AUTONEG_ADVERTISE_REG, - (PHY_100BASETX_FULLDUPLEX_MASK | PHY_100BASETX_HALFDUPLEX_MASK | - PHY_10BASETX_FULLDUPLEX_MASK | PHY_10BASETX_HALFDUPLEX_MASK | 0x1U)); - if (result == kStatus_Success) - { - result = PHY_Write(base, phyAddr, PHY_BASICCONTROL_REG, - (PHY_BCTL_AUTONEG_MASK | PHY_BCTL_RESTART_AUTONEG_MASK)); - if (result == kStatus_Success) - { - /* Check auto negotiation complete. */ - while (counter --) - { - result = PHY_Read(base, phyAddr, PHY_BASICSTATUS_REG, &bssReg); - if ( result == kStatus_Success) - { - PHY_Read(base, phyAddr, PHY_CONTROL1_REG, &ctlReg); - if (((bssReg & PHY_BSTATUS_AUTONEGCOMP_MASK) != 0) && (ctlReg & PHY_LINK_READY_MASK)) - { - /* Wait a moment for Phy status stable. */ - for (timeDelay = 0; timeDelay < PHY_TIMEOUT_COUNT; timeDelay ++) - { - __ASM("nop"); - } - break; - } - } - - if (!counter) - { - return kStatus_PHY_AutoNegotiateFail; - } - } - } - } - } - - return result; -} - -status_t PHY_Write(ENET_Type *base, uint32_t phyAddr, uint32_t phyReg, uint32_t data) -{ - uint32_t counter; - - /* Clear the SMI interrupt event. */ - ENET_ClearInterruptStatus(base, ENET_EIR_MII_MASK); - - /* Starts a SMI write command. */ - ENET_StartSMIWrite(base, phyAddr, phyReg, kENET_MiiWriteValidFrame, data); - - /* Wait for SMI complete. */ - for (counter = PHY_TIMEOUT_COUNT; counter > 0; counter--) - { - if (ENET_GetInterruptStatus(base) & ENET_EIR_MII_MASK) - { - break; - } - } - - /* Check for timeout. */ - if (!counter) - { - return kStatus_PHY_SMIVisitTimeout; - } - - /* Clear MII interrupt event. */ - ENET_ClearInterruptStatus(base, ENET_EIR_MII_MASK); - - return kStatus_Success; -} - -status_t PHY_Read(ENET_Type *base, uint32_t phyAddr, uint32_t phyReg, uint32_t *dataPtr) -{ - assert(dataPtr); - - uint32_t counter; - - /* Clear the MII interrupt event. */ - ENET_ClearInterruptStatus(base, ENET_EIR_MII_MASK); - - /* Starts a SMI read command operation. */ - ENET_StartSMIRead(base, phyAddr, phyReg, kENET_MiiReadValidFrame); - - /* Wait for MII complete. */ - for (counter = PHY_TIMEOUT_COUNT; counter > 0; counter--) - { - if (ENET_GetInterruptStatus(base) & ENET_EIR_MII_MASK) - { - break; - } - } - - /* Check for timeout. */ - if (!counter) - { - return kStatus_PHY_SMIVisitTimeout; - } - - /* Get data from MII register. */ - *dataPtr = ENET_ReadSMIData(base); - - /* Clear MII interrupt event. */ - ENET_ClearInterruptStatus(base, ENET_EIR_MII_MASK); - - return kStatus_Success; -} - -status_t PHY_EnableLoopback(ENET_Type *base, uint32_t phyAddr, phy_loop_t mode, phy_speed_t speed, bool enable) -{ - status_t result; - uint32_t data = 0; - - /* Set the loop mode. */ - if (enable) - { - if (mode == kPHY_LocalLoop) - { - if (speed == kPHY_Speed100M) - { - data = PHY_BCTL_SPEED_100M_MASK | PHY_BCTL_DUPLEX_MASK | PHY_BCTL_LOOP_MASK; - } - else - { - data = PHY_BCTL_DUPLEX_MASK | PHY_BCTL_LOOP_MASK; - } - return PHY_Write(base, phyAddr, PHY_BASICCONTROL_REG, data); - } - else - { - /* First read the current status in control register. */ - result = PHY_Read(base, phyAddr, PHY_CONTROL2_REG, &data); - if (result == kStatus_Success) - { - return PHY_Write(base, phyAddr, PHY_CONTROL2_REG, (data | PHY_CTL2_REMOTELOOP_MASK)); - } - } - } - else - { - /* Disable the loop mode. */ - if (mode == kPHY_LocalLoop) - { - /* First read the current status in control register. */ - result = PHY_Read(base, phyAddr, PHY_BASICCONTROL_REG, &data); - if (result == kStatus_Success) - { - data &= ~PHY_BCTL_LOOP_MASK; - return PHY_Write(base, phyAddr, PHY_BASICCONTROL_REG, (data | PHY_BCTL_RESTART_AUTONEG_MASK)); - } - } - else - { - /* First read the current status in control one register. */ - result = PHY_Read(base, phyAddr, PHY_CONTROL2_REG, &data); - if (result == kStatus_Success) - { - return PHY_Write(base, phyAddr, PHY_CONTROL2_REG, (data & ~PHY_CTL2_REMOTELOOP_MASK)); - } - } - } - return result; -} - -status_t PHY_GetLinkStatus(ENET_Type *base, uint32_t phyAddr, bool *status) -{ - assert(status); - - status_t result = kStatus_Success; - uint32_t data; - - /* Read the basic status register. */ - result = PHY_Read(base, phyAddr, PHY_BASICSTATUS_REG, &data); - if (result == kStatus_Success) - { - if (!(PHY_BSTATUS_LINKSTATUS_MASK & data)) - { - /* link down. */ - *status = false; - } - else - { - /* link up. */ - *status = true; - } - } - return result; -} - -status_t PHY_GetLinkSpeedDuplex(ENET_Type *base, uint32_t phyAddr, phy_speed_t *speed, phy_duplex_t *duplex) -{ - assert(duplex); - - status_t result = kStatus_Success; - uint32_t data, ctlReg; - - /* Read the control two register. */ - result = PHY_Read(base, phyAddr, PHY_CONTROL1_REG, &ctlReg); - if (result == kStatus_Success) - { - data = ctlReg & PHY_CTL1_SPEEDUPLX_MASK; - if ((PHY_CTL1_10FULLDUPLEX_MASK == data) || (PHY_CTL1_100FULLDUPLEX_MASK == data)) - { - /* Full duplex. */ - *duplex = kPHY_FullDuplex; - } - else - { - /* Half duplex. */ - *duplex = kPHY_HalfDuplex; - } - - data = ctlReg & PHY_CTL1_SPEEDUPLX_MASK; - if ((PHY_CTL1_100HALFDUPLEX_MASK == data) || (PHY_CTL1_100FULLDUPLEX_MASK == data)) - { - /* 100M speed. */ - *speed = kPHY_Speed100M; - } - else - { /* 10M speed. */ - *speed = kPHY_Speed10M; - } - } - - return result; -} diff --git a/bsp/imxrt/imxrt1064-nxp-evk/board/ports/phyksz8081/fsl_phy.h b/bsp/imxrt/imxrt1064-nxp-evk/board/ports/phyksz8081/fsl_phy.h deleted file mode 100644 index a1eff6d723..0000000000 --- a/bsp/imxrt/imxrt1064-nxp-evk/board/ports/phyksz8081/fsl_phy.h +++ /dev/null @@ -1,200 +0,0 @@ -/* - * Copyright (c) 2015, Freescale Semiconductor, Inc. - * Copyright 2016-2017 NXP - * All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ -#ifndef _FSL_PHY_H_ -#define _FSL_PHY_H_ - -#include "fsl_enet.h" - -/*! - * @addtogroup phy_driver - * @{ - */ - -/******************************************************************************* - * Definitions - ******************************************************************************/ - -/*! @brief PHY driver version */ -#define FSL_PHY_DRIVER_VERSION (MAKE_VERSION(2, 0, 0)) /*!< Version 2.0.0. */ - -/*! @brief Defines the PHY registers. */ -#define PHY_BASICCONTROL_REG 0x00U /*!< The PHY basic control register. */ -#define PHY_BASICSTATUS_REG 0x01U /*!< The PHY basic status register. */ -#define PHY_ID1_REG 0x02U /*!< The PHY ID one register. */ -#define PHY_ID2_REG 0x03U /*!< The PHY ID two register. */ -#define PHY_AUTONEG_ADVERTISE_REG 0x04U /*!< The PHY auto-negotiate advertise register. */ -#define PHY_CONTROL1_REG 0x1EU /*!< The PHY control one register. */ -#define PHY_CONTROL2_REG 0x1FU /*!< The PHY control two register. */ - -#define PHY_CONTROL_ID1 0x22U /*!< The PHY ID1*/ - -/*! @brief Defines the mask flag in basic control register. */ -#define PHY_BCTL_DUPLEX_MASK 0x0100U /*!< The PHY duplex bit mask. */ -#define PHY_BCTL_RESTART_AUTONEG_MASK 0x0200U /*!< The PHY restart auto negotiation mask. */ -#define PHY_BCTL_AUTONEG_MASK 0x1000U /*!< The PHY auto negotiation bit mask. */ -#define PHY_BCTL_SPEED_MASK 0x2000U /*!< The PHY speed bit mask. */ -#define PHY_BCTL_LOOP_MASK 0x4000U /*!< The PHY loop bit mask. */ -#define PHY_BCTL_RESET_MASK 0x8000U /*!< The PHY reset bit mask. */ -#define PHY_BCTL_SPEED_100M_MASK 0x2000U /*!< The PHY 100M speed mask. */ - -/*!@brief Defines the mask flag of operation mode in control two register*/ -#define PHY_CTL2_REMOTELOOP_MASK 0x0004U /*!< The PHY remote loopback mask. */ -#define PHY_CTL2_REFCLK_SELECT_MASK 0x0080U /*!< The PHY RMII reference clock select. */ -#define PHY_CTL1_10HALFDUPLEX_MASK 0x0001U /*!< The PHY 10M half duplex mask. */ -#define PHY_CTL1_100HALFDUPLEX_MASK 0x0002U /*!< The PHY 100M half duplex mask. */ -#define PHY_CTL1_10FULLDUPLEX_MASK 0x0005U /*!< The PHY 10M full duplex mask. */ -#define PHY_CTL1_100FULLDUPLEX_MASK 0x0006U /*!< The PHY 100M full duplex mask. */ -#define PHY_CTL1_SPEEDUPLX_MASK 0x0007U /*!< The PHY speed and duplex mask. */ -#define PHY_CTL1_ENERGYDETECT_MASK 0x10U /*!< The PHY signal present on rx differential pair. */ -#define PHY_CTL1_LINKUP_MASK 0x100U /*!< The PHY link up. */ -#define PHY_LINK_READY_MASK (PHY_CTL1_ENERGYDETECT_MASK | PHY_CTL1_LINKUP_MASK) - -/*! @brief Defines the mask flag in basic status register. */ -#define PHY_BSTATUS_LINKSTATUS_MASK 0x0004U /*!< The PHY link status mask. */ -#define PHY_BSTATUS_AUTONEGABLE_MASK 0x0008U /*!< The PHY auto-negotiation ability mask. */ -#define PHY_BSTATUS_AUTONEGCOMP_MASK 0x0020U /*!< The PHY auto-negotiation complete mask. */ - -/*! @brief Defines the mask flag in PHY auto-negotiation advertise register. */ -#define PHY_100BaseT4_ABILITY_MASK 0x200U /*!< The PHY have the T4 ability. */ -#define PHY_100BASETX_FULLDUPLEX_MASK 0x100U /*!< The PHY has the 100M full duplex ability.*/ -#define PHY_100BASETX_HALFDUPLEX_MASK 0x080U /*!< The PHY has the 100M full duplex ability.*/ -#define PHY_10BASETX_FULLDUPLEX_MASK 0x040U /*!< The PHY has the 10M full duplex ability.*/ -#define PHY_10BASETX_HALFDUPLEX_MASK 0x020U /*!< The PHY has the 10M full duplex ability.*/ - -/*! @brief Defines the PHY status. */ -enum _phy_status -{ - kStatus_PHY_SMIVisitTimeout = MAKE_STATUS(kStatusGroup_PHY, 1), /*!< ENET PHY SMI visit timeout. */ - kStatus_PHY_AutoNegotiateFail = MAKE_STATUS(kStatusGroup_PHY, 2) /*!< ENET PHY AutoNegotiate Fail. */ -}; - -/*! @brief Defines the PHY link speed. This is align with the speed for ENET MAC. */ -typedef enum _phy_speed -{ - kPHY_Speed10M = 0U, /*!< ENET PHY 10M speed. */ - kPHY_Speed100M /*!< ENET PHY 100M speed. */ -} phy_speed_t; - -/*! @brief Defines the PHY link duplex. */ -typedef enum _phy_duplex -{ - kPHY_HalfDuplex = 0U, /*!< ENET PHY half duplex. */ - kPHY_FullDuplex /*!< ENET PHY full duplex. */ -} phy_duplex_t; - -/*! @brief Defines the PHY loopback mode. */ -typedef enum _phy_loop -{ - kPHY_LocalLoop = 0U, /*!< ENET PHY local loopback. */ - kPHY_RemoteLoop /*!< ENET PHY remote loopback. */ -} phy_loop_t; - -/******************************************************************************* - * API - ******************************************************************************/ - -#if defined(__cplusplus) -extern "C" { -#endif - -/*! - * @name PHY Driver - * @{ - */ - -/*! - * @brief Initializes PHY. - * - * This function initialize the SMI interface and initialize PHY. - * The SMI is the MII management interface between PHY and MAC, which should be - * firstly initialized before any other operation for PHY. The PHY initialize with auto-negotiation. - * - * @param base ENET peripheral base address. - * @param phyAddr The PHY address. - * @param srcClock_Hz The module clock frequency - system clock for MII management interface - SMI. - * @retval kStatus_Success PHY initialize success - * @retval kStatus_PHY_SMIVisitTimeout PHY SMI visit time out - * @retval kStatus_PHY_AutoNegotiateFail PHY auto negotiate fail - */ -status_t PHY_Init(ENET_Type *base, uint32_t phyAddr, uint32_t srcClock_Hz); - -/*! - * @brief PHY Write function. This function write data over the SMI to - * the specified PHY register. This function is called by all PHY interfaces. - * - * @param base ENET peripheral base address. - * @param phyAddr The PHY address. - * @param phyReg The PHY register. - * @param data The data written to the PHY register. - * @retval kStatus_Success PHY write success - * @retval kStatus_PHY_SMIVisitTimeout PHY SMI visit time out - */ -status_t PHY_Write(ENET_Type *base, uint32_t phyAddr, uint32_t phyReg, uint32_t data); - -/*! - * @brief PHY Read function. This interface read data over the SMI from the - * specified PHY register. This function is called by all PHY interfaces. - * - * @param base ENET peripheral base address. - * @param phyAddr The PHY address. - * @param phyReg The PHY register. - * @param dataPtr The address to store the data read from the PHY register. - * @retval kStatus_Success PHY read success - * @retval kStatus_PHY_SMIVisitTimeout PHY SMI visit time out - */ -status_t PHY_Read(ENET_Type *base, uint32_t phyAddr, uint32_t phyReg, uint32_t *dataPtr); - -/*! - * @brief Enables/disables PHY loopback. - * - * @param base ENET peripheral base address. - * @param phyAddr The PHY address. - * @param mode The loopback mode to be enabled, please see "phy_loop_t". - * the two loopback mode should not be both set. when one loopback mode is set - * the other one should be disabled. - * @param speed PHY speed for loopback mode. - * @param enable True to enable, false to disable. - * @retval kStatus_Success PHY loopback success - * @retval kStatus_PHY_SMIVisitTimeout PHY SMI visit time out - */ -status_t PHY_EnableLoopback(ENET_Type *base, uint32_t phyAddr, phy_loop_t mode, phy_speed_t speed, bool enable); - -/*! - * @brief Gets the PHY link status. - * - * @param base ENET peripheral base address. - * @param phyAddr The PHY address. - * @param status The link up or down status of the PHY. - * - true the link is up. - * - false the link is down. - * @retval kStatus_Success PHY get link status success - * @retval kStatus_PHY_SMIVisitTimeout PHY SMI visit time out - */ -status_t PHY_GetLinkStatus(ENET_Type *base, uint32_t phyAddr, bool *status); - -/*! - * @brief Gets the PHY link speed and duplex. - * - * @param base ENET peripheral base address. - * @param phyAddr The PHY address. - * @param speed The address of PHY link speed. - * @param duplex The link duplex of PHY. - * @retval kStatus_Success PHY get link speed and duplex success - * @retval kStatus_PHY_SMIVisitTimeout PHY SMI visit time out - */ -status_t PHY_GetLinkSpeedDuplex(ENET_Type *base, uint32_t phyAddr, phy_speed_t *speed, phy_duplex_t *duplex); - -/* @} */ - -#if defined(__cplusplus) -} -#endif - -/*! @}*/ - -#endif /* _FSL_PHY_H_ */ diff --git a/bsp/imxrt/libraries/drivers/SConscript b/bsp/imxrt/libraries/drivers/SConscript index c806dada25..c610fcd082 100644 --- a/bsp/imxrt/libraries/drivers/SConscript +++ b/bsp/imxrt/libraries/drivers/SConscript @@ -44,6 +44,9 @@ if GetDepend('BSP_USING_LCD'): if GetDepend('BSP_USING_ETH'): src += ['drv_eth.c'] + +if GetDepend('BSP_USING_PHY'): + src += ['drv_mdio.c'] if GetDepend('BSP_USING_USB_DEVICE'): src += ['drv_usbd.c'] diff --git a/bsp/imxrt/libraries/drivers/drv_eth.c b/bsp/imxrt/libraries/drivers/drv_eth.c index 4558312be8..665886f936 100644 --- a/bsp/imxrt/libraries/drivers/drv_eth.c +++ b/bsp/imxrt/libraries/drivers/drv_eth.c @@ -19,7 +19,6 @@ #include "fsl_enet.h" #include "fsl_gpio.h" -#include "fsl_phy.h" #include "fsl_cache.h" #include "fsl_iomuxc.h" #include "fsl_common.h" @@ -537,31 +536,52 @@ struct pbuf *rt_imxrt_eth_rx(rt_device_t dev) return NULL; } +#ifdef BSP_USING_PHY +static struct rt_phy_device *phy_dev = RT_NULL; static void phy_monitor_thread_entry(void *parameter) { - phy_speed_t speed; - phy_duplex_t duplex; - bool link = false; + rt_uint32_t speed; + rt_uint32_t duplex; + rt_bool_t link = RT_FALSE; - imxrt_enet_phy_reset_by_gpio(); - - PHY_Init(imxrt_eth_device.enet_base, PHY_ADDRESS, CLOCK_GetFreq(kCLOCK_AhbClk)); + phy_dev = (struct rt_phy_device *)rt_device_find("rtt-phy"); + if ((RT_NULL == phy_dev) || (RT_NULL == phy_dev->ops)) + { + // TODO print warning information + LOG_E("Can not find phy device called \"rtt-phy\""); + return ; + } + LOG_I("start to initialize phy device!"); + if (RT_NULL == phy_dev->ops->init) + { + LOG_E("phy driver error!"); + return ; + } + rt_phy_status status = phy_dev->ops->init(imxrt_eth_device.enet_base, PHY_DEVICE_ADDRESS, CLOCK_GetFreq(kCLOCK_AhbClk)); + if (PHY_STATUS_OK != status) + { + LOG_E("Phy device initialize unsuccessful!\n"); + return ; + } + else + { + LOG_I("Phy device initialize successful!\n"); + } while (1) { - bool new_link = false; - status_t status = PHY_GetLinkStatus(imxrt_eth_device.enet_base, PHY_ADDRESS, &new_link); + rt_bool_t new_link = RT_FALSE; + rt_phy_status status = phy_dev->ops->get_link_status(&new_link); - if ((status == kStatus_Success) && (link != new_link)) + if ((PHY_STATUS_OK == status) && (link != new_link)) { link = new_link; - if (link) // link up + if (link) // link up { - PHY_GetLinkSpeedDuplex(imxrt_eth_device.enet_base, - PHY_ADDRESS, &speed, &duplex); + phy_dev->ops->get_link_speed_duplex(&speed, &duplex); - if (kPHY_Speed10M == speed) + if (PHY_SPEED_10M == speed) { dbg_log(DBG_LOG, "10M\n"); } @@ -570,7 +590,7 @@ static void phy_monitor_thread_entry(void *parameter) dbg_log(DBG_LOG, "100M\n"); } - if (kPHY_HalfDuplex == duplex) + if (PHY_HALF_DUPLEX == duplex) { dbg_log(DBG_LOG, "half dumplex\n"); } @@ -579,8 +599,7 @@ static void phy_monitor_thread_entry(void *parameter) dbg_log(DBG_LOG, "full dumplex\n"); } - if ((imxrt_eth_device.speed != (enet_mii_speed_t)speed) - || (imxrt_eth_device.duplex != (enet_mii_duplex_t)duplex)) + if ((imxrt_eth_device.speed != (enet_mii_speed_t)speed) || (imxrt_eth_device.duplex != (enet_mii_duplex_t)duplex)) { imxrt_eth_device.speed = (enet_mii_speed_t)speed; imxrt_eth_device.duplex = (enet_mii_duplex_t)duplex; @@ -605,6 +624,7 @@ static void phy_monitor_thread_entry(void *parameter) rt_thread_delay(RT_TICK_PER_SECOND * 2); } } +#endif static int rt_hw_imxrt_eth_init(void) { @@ -657,6 +677,7 @@ static int rt_hw_imxrt_eth_init(void) /* start phy monitor */ { + #ifdef BSP_USING_PHY rt_thread_t tid; tid = rt_thread_create("phy", phy_monitor_thread_entry, @@ -666,6 +687,7 @@ static int rt_hw_imxrt_eth_init(void) 2); if (tid != RT_NULL) rt_thread_startup(tid); + #endif } return state; @@ -673,50 +695,47 @@ static int rt_hw_imxrt_eth_init(void) INIT_DEVICE_EXPORT(rt_hw_imxrt_eth_init); #endif -#ifdef RT_USING_FINSH +#if defined(RT_USING_FINSH) && defined(RT_USING_PHY) #include -void phy_read(uint32_t phyReg) +void phy_read(rt_uint32_t phy_reg) { - uint32_t data; - status_t status; + rt_uint32_t data; - status = PHY_Read(imxrt_eth_device.enet_base, PHY_ADDRESS, phyReg, &data); - if (kStatus_Success == status) + rt_phy_status status = phy_dev->ops->read(phy_reg, &data); + if (PHY_STATUS_OK == status) { - rt_kprintf("PHY_Read: %02X --> %08X", phyReg, data); + rt_kprintf("PHY_Read: %02X --> %08X", phy_reg, data); } else { - rt_kprintf("PHY_Read: %02X --> faild", phyReg); + rt_kprintf("PHY_Read: %02X --> faild", phy_reg); } } -void phy_write(uint32_t phyReg, uint32_t data) +void phy_write(rt_uint32_t phy_reg, rt_uint32_t data) { - status_t status; - - status = PHY_Write(imxrt_eth_device.enet_base, PHY_ADDRESS, phyReg, data); - if (kStatus_Success == status) + rt_phy_status status = phy_dev->ops->write(phy_reg, data); + if (PHY_STATUS_OK == status) { - rt_kprintf("PHY_Write: %02X --> %08X\n", phyReg, data); + rt_kprintf("PHY_Write: %02X --> %08X\n", phy_reg, data); } else { - rt_kprintf("PHY_Write: %02X --> faild\n", phyReg); + rt_kprintf("PHY_Write: %02X --> faild\n", phy_reg); } } void phy_dump(void) { - uint32_t data; - status_t status; + rt_uint32_t data; + rt_phy_status status; int i; for (i = 0; i < 32; i++) { - status = PHY_Read(imxrt_eth_device.enet_base, PHY_ADDRESS, i, &data); - if (kStatus_Success != status) + status = phy_dev->ops->read(i, &data); + if (PHY_STATUS_OK != status) { rt_kprintf("phy_dump: %02X --> faild", i); break; @@ -730,10 +749,11 @@ void phy_dump(void) { rt_kprintf("%02X --> %08X\n", i, data); } - } } +#endif +#if defined(RT_USING_FINSH) && defined(RT_USING_LWIP) void enet_reg_dump(void) { ENET_Type *enet_base = imxrt_eth_device.enet_base; diff --git a/bsp/imxrt/libraries/drivers/drv_mdio.c b/bsp/imxrt/libraries/drivers/drv_mdio.c new file mode 100644 index 0000000000..3e98d57f29 --- /dev/null +++ b/bsp/imxrt/libraries/drivers/drv_mdio.c @@ -0,0 +1,160 @@ + +/* + * Copyright (c) 2006-2020, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2020-09-29 WangQiang the first version + * + */ + +#include + +#ifdef BSP_USING_PHY + +#define LOG_TAG "drv.mdio" +#include + +#include +#include "drv_mdio.h" + + + +/*! @brief Defines the timeout macro. */ +#define PHY_TIMEOUT_COUNT 0x3FFFFFFU + +/*! + * @brief Get the ENET instance from peripheral base address. + * + * @param base ENET peripheral base address. + * @return ENET instance. + */ +extern uint32_t ENET_GetInstance(ENET_Type *base); + +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) +/*! @brief Pointers to enet clocks for each instance. */ +extern clock_ip_name_t s_enetClock[FSL_FEATURE_SOC_ENET_COUNT]; +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ + +static rt_bool_t rt_hw_mdio_init(void *bus, rt_uint32_t src_clock_hz) +{ + struct rt_mdio_bus *bus_obj = (struct rt_mdio_bus *)bus; + uint32_t instance = ENET_GetInstance((ENET_Type *)(bus_obj->hw_obj)); +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) + /* Set SMI first. */ + CLOCK_EnableClock(s_enetClock[instance]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ + ENET_SetSMI((ENET_Type *)(bus_obj->hw_obj), src_clock_hz, RT_FALSE); + + return RT_TRUE; +} + +static rt_size_t rt_hw_mdio_read(void *bus, rt_uint32_t addr, rt_uint32_t reg, void *data, rt_uint32_t size) +{ + RT_ASSERT(data); + struct rt_mdio_bus *bus_obj = (struct rt_mdio_bus *)bus; + + rt_uint32_t counter; + rt_uint32_t *data_ptr = (rt_uint32_t *)data; + + if (4 != size) + { + return 0; + } + + /* Clear the MII interrupt event. */ + ENET_ClearInterruptStatus((ENET_Type *)(bus_obj->hw_obj), ENET_EIR_MII_MASK); + + /* Starts a SMI read command operation. */ + ENET_StartSMIRead((ENET_Type *)(bus_obj->hw_obj), addr, reg, kENET_MiiReadValidFrame); + + /* Wait for MII complete. */ + for (counter = PHY_TIMEOUT_COUNT; counter > 0; counter--) + { + if (ENET_GetInterruptStatus((ENET_Type *)(bus_obj->hw_obj)) & ENET_EIR_MII_MASK) + { + break; + } + } + + /* Check for timeout. */ + if (!counter) + { + // return kStatus_PHY_SMIVisitTimeout; + return 0; + } + + /* Get data from MII register. */ + *data_ptr = ENET_ReadSMIData((ENET_Type *)(bus_obj->hw_obj)); + + /* Clear MII interrupt event. */ + ENET_ClearInterruptStatus((ENET_Type *)bus_obj->hw_obj, ENET_EIR_MII_MASK); + + return 4; +} + + +static rt_size_t rt_hw_mdio_write(void *bus, rt_uint32_t addr, rt_uint32_t reg, void *data, rt_uint32_t size) +{ + struct rt_mdio_bus *bus_obj = (struct rt_mdio_bus *)bus; + uint32_t counter; + rt_uint32_t *data_ptr = (rt_uint32_t *)data; + + if (4 != size) + { + return 0; + } + + /* Clear the SMI interrupt event. */ + ENET_ClearInterruptStatus((ENET_Type *)(bus_obj->hw_obj), ENET_EIR_MII_MASK); + + /* Starts a SMI write command. */ + ENET_StartSMIWrite((ENET_Type *)(bus_obj->hw_obj), addr, reg, kENET_MiiWriteValidFrame, *data_ptr); + + /* Wait for SMI complete. */ + for (counter = PHY_TIMEOUT_COUNT; counter > 0; counter--) + { + if (ENET_GetInterruptStatus((ENET_Type *)(bus_obj->hw_obj)) & ENET_EIR_MII_MASK) + { + break; + } + } + + /* Check for timeout. */ + if (!counter) + { + return 0; + } + + /* Clear MII interrupt event. */ + ENET_ClearInterruptStatus((ENET_Type *)(bus_obj->hw_obj), ENET_EIR_MII_MASK); + + return size; +} + +static struct rt_mdio_bus_ops imxrt_mdio_ops = +{ + .init = rt_hw_mdio_init, + .read = rt_hw_mdio_read, + .write = rt_hw_mdio_write, + .uninit = RT_NULL, +}; + +static rt_mdio_t mdio_bus; + +rt_mdio_t *rt_hw_mdio_register(void *hw_obj, char *name) +{ + mdio_bus.hw_obj = hw_obj; + mdio_bus.name = name; + mdio_bus.ops = &imxrt_mdio_ops; + return &mdio_bus; +} + +rt_mdio_t *rt_hw_mdio_get(void) +{ + return &mdio_bus; +} + +#endif diff --git a/bsp/imxrt/libraries/drivers/drv_mdio.h b/bsp/imxrt/libraries/drivers/drv_mdio.h new file mode 100644 index 0000000000..a1623cfc2c --- /dev/null +++ b/bsp/imxrt/libraries/drivers/drv_mdio.h @@ -0,0 +1,25 @@ + +/* + * Copyright (c) 2006-2020, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2020-09-29 WangQiang the first version + * + */ + +#ifndef DRV_MDIO_H__ +#define DRV_MDIO_H__ + +#include + +#include "fsl_enet.h" + + +rt_mdio_t *rt_hw_mdio_register(void *hw_obj, char *name); + +rt_mdio_t *rt_hw_mdio_get(void); + +#endif /*DRV_MDIO_H__*/ diff --git a/bsp/imxrt/libraries/peripherals/SConscript b/bsp/imxrt/libraries/peripherals/SConscript new file mode 100644 index 0000000000..13d040cf2b --- /dev/null +++ b/bsp/imxrt/libraries/peripherals/SConscript @@ -0,0 +1,16 @@ +from building import * + +src = [] +cwd = [] +CPPDEFINES = [] + +cwd = GetCurrentDir() + +if GetDepend('BSP_USING_PHY') and GetDepend('PHY_USING_KSZ8081'): + src += ['phyksz8081.c'] + +path = [cwd] + +group = DefineGroup('Peripherals', src, depend = [''], CPPPATH = path, CPPDEFINES=CPPDEFINES) + +Return('group') diff --git a/bsp/imxrt/libraries/peripherals/phyksz8081.c b/bsp/imxrt/libraries/peripherals/phyksz8081.c new file mode 100644 index 0000000000..88c041f4d1 --- /dev/null +++ b/bsp/imxrt/libraries/peripherals/phyksz8081.c @@ -0,0 +1,367 @@ +/* + * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#ifdef PHY_USING_KSZ8081 + +#include +#include "drv_gpio.h" +#include "drv_mdio.h" + + +/******************************************************************************* + * Definitions + ******************************************************************************/ + +/*! @brief Defines the PHY registers. */ +#define PHY_BASICCONTROL_REG 0x00U /*!< The PHY basic control register. */ +#define PHY_BASICSTATUS_REG 0x01U /*!< The PHY basic status register. */ +#define PHY_ID1_REG 0x02U /*!< The PHY ID one register. */ +#define PHY_ID2_REG 0x03U /*!< The PHY ID two register. */ +#define PHY_AUTONEG_ADVERTISE_REG 0x04U /*!< The PHY auto-negotiate advertise register. */ +#define PHY_CONTROL1_REG 0x1EU /*!< The PHY control one register. */ +#define PHY_CONTROL2_REG 0x1FU /*!< The PHY control two register. */ + +#define PHY_CONTROL_ID1 0x22U /*!< The PHY ID1*/ + +/*! @brief Defines the mask flag in basic control register. */ +#define PHY_BCTL_DUPLEX_MASK 0x0100U /*!< The PHY duplex bit mask. */ +#define PHY_BCTL_RESTART_AUTONEG_MASK 0x0200U /*!< The PHY restart auto negotiation mask. */ +#define PHY_BCTL_AUTONEG_MASK 0x1000U /*!< The PHY auto negotiation bit mask. */ +#define PHY_BCTL_SPEED_MASK 0x2000U /*!< The PHY speed bit mask. */ +#define PHY_BCTL_LOOP_MASK 0x4000U /*!< The PHY loop bit mask. */ +#define PHY_BCTL_RESET_MASK 0x8000U /*!< The PHY reset bit mask. */ +#define PHY_BCTL_SPEED_100M_MASK 0x2000U /*!< The PHY 100M speed mask. */ + +/*!@brief Defines the mask flag of operation mode in control two register*/ +#define PHY_CTL2_REMOTELOOP_MASK 0x0004U /*!< The PHY remote loopback mask. */ +#define PHY_CTL2_REFCLK_SELECT_MASK 0x0080U /*!< The PHY RMII reference clock select. */ +#define PHY_CTL1_10HALFDUPLEX_MASK 0x0001U /*!< The PHY 10M half duplex mask. */ +#define PHY_CTL1_100HALFDUPLEX_MASK 0x0002U /*!< The PHY 100M half duplex mask. */ +#define PHY_CTL1_10FULLDUPLEX_MASK 0x0005U /*!< The PHY 10M full duplex mask. */ +#define PHY_CTL1_100FULLDUPLEX_MASK 0x0006U /*!< The PHY 100M full duplex mask. */ +#define PHY_CTL1_SPEEDUPLX_MASK 0x0007U /*!< The PHY speed and duplex mask. */ +#define PHY_CTL1_ENERGYDETECT_MASK 0x10U /*!< The PHY signal present on rx differential pair. */ +#define PHY_CTL1_LINKUP_MASK 0x100U /*!< The PHY link up. */ +#define PHY_LINK_READY_MASK (PHY_CTL1_ENERGYDETECT_MASK | PHY_CTL1_LINKUP_MASK) + +/*! @brief Defines the mask flag in basic status register. */ +#define PHY_BSTATUS_LINKSTATUS_MASK 0x0004U /*!< The PHY link status mask. */ +#define PHY_BSTATUS_AUTONEGABLE_MASK 0x0008U /*!< The PHY auto-negotiation ability mask. */ +#define PHY_BSTATUS_AUTONEGCOMP_MASK 0x0020U /*!< The PHY auto-negotiation complete mask. */ + +/*! @brief Defines the mask flag in PHY auto-negotiation advertise register. */ +#define PHY_100BaseT4_ABILITY_MASK 0x200U /*!< The PHY have the T4 ability. */ +#define PHY_100BASETX_FULLDUPLEX_MASK 0x100U /*!< The PHY has the 100M full duplex ability.*/ +#define PHY_100BASETX_HALFDUPLEX_MASK 0x080U /*!< The PHY has the 100M full duplex ability.*/ +#define PHY_10BASETX_FULLDUPLEX_MASK 0x040U /*!< The PHY has the 10M full duplex ability.*/ +#define PHY_10BASETX_HALFDUPLEX_MASK 0x020U /*!< The PHY has the 10M full duplex ability.*/ + + + +/*! @brief Defines the timeout macro. */ +#define PHY_TIMEOUT_COUNT 0x3FFFFFFU + +/* defined the Reset pin, PORT and PIN config by menuconfig */ +#define RESET_PIN GET_PIN(PHY_RESET_PORT, PHY_RESET_PIN) + +/******************************************************************************* + * Prototypes + ******************************************************************************/ + + +/******************************************************************************* + * Variables + ******************************************************************************/ +static struct rt_phy_device phy_ksz8081; + +/******************************************************************************* + * Code + ******************************************************************************/ + + + +static inline rt_bool_t read_reg(rt_mdio_t *bus, rt_uint32_t addr, rt_uint32_t reg_id, rt_uint32_t *value) +{ + if (4 != bus->ops->read(bus, addr, reg_id, value, 4)) + { + return RT_FALSE; + } + return RT_TRUE; +} + +static inline rt_bool_t write_reg(rt_mdio_t *bus, rt_uint32_t addr, rt_uint32_t reg_id, rt_uint32_t value) +{ + if (4 != bus->ops->write(bus, addr, reg_id, &value, 4)) + { + return RT_FALSE; + } + return RT_TRUE; +} + +static rt_phy_status rt_phy_init(void *object, rt_uint32_t phy_addr, rt_uint32_t src_clock_hz) +{ + rt_bool_t ret; + rt_phy_status result; + rt_uint32_t counter = PHY_TIMEOUT_COUNT; + rt_uint32_t id_reg = 0; + rt_uint32_t time_delay; + rt_uint32_t bss_reg; + rt_uint32_t ctl_reg = 0; + + // reset phy device by gpio + rt_pin_mode(RESET_PIN, PIN_MODE_OUTPUT); + rt_pin_write(RESET_PIN, PIN_LOW); + rt_thread_mdelay(100); + rt_pin_write(RESET_PIN, PIN_HIGH); + + rt_mdio_t *mdio_bus = rt_hw_mdio_register(object, "phy_mdio"); + if (RT_NULL == mdio_bus) + { + return PHY_STATUS_FAIL; + } + phy_ksz8081.bus = mdio_bus; + phy_ksz8081.addr = phy_addr; + ret = mdio_bus->ops->init(mdio_bus, src_clock_hz); + if ( !ret ) + { + return PHY_STATUS_FAIL; + } + + /* Initialization after PHY stars to work. */ + while ((id_reg != PHY_CONTROL_ID1) && (counter != 0)) + { + phy_ksz8081.ops->read(PHY_ID1_REG, &id_reg); + counter--; + } + + if (!counter) + { + return PHY_STATUS_FAIL; + } + + /* Reset PHY. */ + counter = PHY_TIMEOUT_COUNT; + result = phy_ksz8081.ops->write(PHY_BASICCONTROL_REG, PHY_BCTL_RESET_MASK); + if (PHY_STATUS_OK == result) + { + #if defined(FSL_FEATURE_PHYKSZ8081_USE_RMII50M_MODE) + rt_uint32_t data = 0; + result = phy_ksz8081.ops->read(PHY_CONTROL2_REG, &data); + if (PHY_STATUS_FAIL == result) + { + return PHY_STATUS_FAIL; + } + result = phy_ksz8081.ops->write(PHY_CONTROL2_REG, (data | PHY_CTL2_REFCLK_SELECT_MASK)); + if (PHY_STATUS_FAIL == result) + { + return PHY_STATUS_FAIL; + } + #endif /* FSL_FEATURE_PHYKSZ8081_USE_RMII50M_MODE */ + + /* Set the negotiation. */ + result = phy_ksz8081.ops->write(PHY_AUTONEG_ADVERTISE_REG, + (PHY_100BASETX_FULLDUPLEX_MASK | PHY_100BASETX_HALFDUPLEX_MASK | + PHY_10BASETX_FULLDUPLEX_MASK | PHY_10BASETX_HALFDUPLEX_MASK | 0x1U)); + if (PHY_STATUS_OK == result) + { + result = phy_ksz8081.ops->write(PHY_BASICCONTROL_REG, (PHY_BCTL_AUTONEG_MASK | PHY_BCTL_RESTART_AUTONEG_MASK)); + if (PHY_STATUS_OK == result) + { + /* Check auto negotiation complete. */ + while (counter--) + { + result = phy_ksz8081.ops->read(PHY_BASICSTATUS_REG, &bss_reg); + if (PHY_STATUS_OK == result) + { + phy_ksz8081.ops->read(PHY_CONTROL1_REG, &ctl_reg); + if (((bss_reg & PHY_BSTATUS_AUTONEGCOMP_MASK) != 0) && (ctl_reg & PHY_LINK_READY_MASK)) + { + /* Wait a moment for Phy status stable. */ + for (time_delay = 0; time_delay < PHY_TIMEOUT_COUNT; time_delay++) + { + __ASM("nop"); + } + break; + } + } + + if (!counter) + { + return PHY_STATUS_FAIL; + } + } + } + } + } + + return PHY_STATUS_OK; +} + + +static rt_phy_status rt_phy_read(rt_uint32_t reg, rt_uint32_t *data) +{ + rt_mdio_t *mdio_bus = phy_ksz8081.bus; + rt_uint32_t device_id = phy_ksz8081.addr; + + if (read_reg(mdio_bus, device_id, reg, data)) + { + return PHY_STATUS_OK; + } + return PHY_STATUS_FAIL; +} + +static rt_phy_status rt_phy_write(rt_uint32_t reg, rt_uint32_t data) +{ + rt_mdio_t *mdio_bus = phy_ksz8081.bus; + rt_uint32_t device_id = phy_ksz8081.addr; + + if (write_reg(mdio_bus, device_id, reg, data)) + { + return PHY_STATUS_OK; + } + return PHY_STATUS_FAIL; +} + +static rt_phy_status rt_phy_loopback(rt_uint32_t mode, rt_uint32_t speed, rt_bool_t enable) +{ + rt_uint32_t data = 0; + rt_phy_status result; + + /* Set the loop mode. */ + if (enable) + { + if (PHY_LOCAL_LOOP == mode) + { + if (PHY_SPEED_100M == speed) + { + data = PHY_BCTL_SPEED_100M_MASK | PHY_BCTL_DUPLEX_MASK | PHY_BCTL_LOOP_MASK; + } + else + { + data = PHY_BCTL_DUPLEX_MASK | PHY_BCTL_LOOP_MASK; + } + return phy_ksz8081.ops->write(PHY_BASICCONTROL_REG, data); + } + else + { + /* First read the current status in control register. */ + result = phy_ksz8081.ops->read(PHY_CONTROL2_REG, &data); + if (PHY_STATUS_OK == result) + { + return phy_ksz8081.ops->write(PHY_CONTROL2_REG, (data | PHY_CTL2_REMOTELOOP_MASK)); + } + } + } + else + { + /* Disable the loop mode. */ + if (PHY_LOCAL_LOOP == mode) + { + /* First read the current status in control register. */ + result = phy_ksz8081.ops->read(PHY_BASICCONTROL_REG, &data); + if (PHY_STATUS_OK == result) + { + data &= ~PHY_BCTL_LOOP_MASK; + return phy_ksz8081.ops->write(PHY_BASICCONTROL_REG, (data | PHY_BCTL_RESTART_AUTONEG_MASK)); + } + } + else + { + /* First read the current status in control one register. */ + result = phy_ksz8081.ops->read(PHY_CONTROL2_REG, &data); + if (PHY_STATUS_OK == result) + { + return phy_ksz8081.ops->write(PHY_CONTROL2_REG, (data & ~PHY_CTL2_REMOTELOOP_MASK)); + } + } + } + return result; +} + +static rt_phy_status get_link_status(rt_bool_t *status) +{ + rt_phy_status result; + rt_uint32_t data; + + /* Read the basic status register. */ + result = phy_ksz8081.ops->read(PHY_BASICSTATUS_REG, &data); + if (PHY_STATUS_OK == result) + { + if (!(PHY_BSTATUS_LINKSTATUS_MASK & data)) + { + /* link down. */ + *status = RT_FALSE; + } + else + { + /* link up. */ + *status = RT_TRUE; + } + } + return result; +} +static rt_phy_status get_link_speed_duplex(rt_uint32_t *speed, rt_uint32_t *duplex) +{ + rt_phy_status result = PHY_STATUS_OK; + rt_uint32_t data, ctl_reg; + + /* Read the control two register. */ + result = phy_ksz8081.ops->read(PHY_CONTROL1_REG, &ctl_reg); + if (PHY_STATUS_OK == result) + { + data = ctl_reg & PHY_CTL1_SPEEDUPLX_MASK; + if ((PHY_CTL1_10FULLDUPLEX_MASK == data) || (PHY_CTL1_100FULLDUPLEX_MASK == data)) + { + /* Full duplex. */ + *duplex = PHY_FULL_DUPLEX; + } + else + { + /* Half duplex. */ + *duplex = PHY_HALF_DUPLEX; + } + + data = ctl_reg & PHY_CTL1_SPEEDUPLX_MASK; + if ((PHY_CTL1_100HALFDUPLEX_MASK == data) || (PHY_CTL1_100FULLDUPLEX_MASK == data)) + { + /* 100M speed. */ + *speed = PHY_SPEED_100M; + } + else + { /* 10M speed. */ + *speed = PHY_SPEED_10M; + } + } + + return result; +} + +static struct rt_phy_ops phy_ops = +{ + .init = rt_phy_init, + .read = rt_phy_read, + .write = rt_phy_write, + .loopback = rt_phy_loopback, + .get_link_status = get_link_status, + .get_link_speed_duplex = get_link_speed_duplex, +}; + +static int rt_phy_ksz8081_register( void ) +{ + phy_ksz8081.ops = &phy_ops; + rt_hw_phy_register(&phy_ksz8081, "rtt-phy"); + return 1; +} + +INIT_DEVICE_EXPORT(rt_phy_ksz8081_register); + + + +#endif /* PHY_USING_KSZ8081 */ diff --git a/bsp/imxrt/tools/sdk_dist.py b/bsp/imxrt/tools/sdk_dist.py index 89b7da4356..b663628504 100644 --- a/bsp/imxrt/tools/sdk_dist.py +++ b/bsp/imxrt/tools/sdk_dist.py @@ -21,3 +21,6 @@ def dist_do_building(BSP_ROOT, dist_dir=None): print("=> copy bsp drivers") bsp_copy_files(os.path.join(library_path, 'drivers'), os.path.join(library_dir, 'drivers')) shutil.copyfile(os.path.join(library_path, 'Kconfig'), os.path.join(library_dir, 'Kconfig')) + + print("=> copy bsp peripherals") + bsp_copy_files(os.path.join(library_path, 'peripherals'), os.path.join(library_dir, 'peripherals')) diff --git a/components/drivers/Kconfig b/components/drivers/Kconfig index 457b8751fe..db4455160e 100755 --- a/components/drivers/Kconfig +++ b/components/drivers/Kconfig @@ -103,6 +103,10 @@ if RT_USING_I2C endif endif +config RT_USING_PHY + bool "Using ethernet phy device drivers" + default n + config RT_USING_PIN bool "Using generic GPIO device drivers" default y diff --git a/components/drivers/include/drivers/phy.h b/components/drivers/include/drivers/phy.h new file mode 100644 index 0000000000..9a9eaeb5dd --- /dev/null +++ b/components/drivers/include/drivers/phy.h @@ -0,0 +1,79 @@ + + +#ifndef __PHY_H___ +#define __PHY_H___ + +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* Defines the PHY link speed. This is align with the speed for MAC. */ +enum phy_speed +{ + PHY_SPEED_10M = 0U, /* PHY 10M speed. */ + PHY_SPEED_100M /* PHY 100M speed. */ +}; + +/* Defines the PHY link duplex. */ +enum phy_duplex +{ + PHY_HALF_DUPLEX = 0U, /* PHY half duplex. */ + PHY_FULL_DUPLEX /* PHY full duplex. */ +}; + +/*! @brief Defines the PHY loopback mode. */ +enum phy_loop +{ + PHY_LOCAL_LOOP = 0U, /* PHY local loopback. */ + PHY_REMOTE_LOOP /* PHY remote loopback. */ +}; + + +struct rt_phy_msg +{ + rt_uint32_t reg; + rt_uint32_t value; +}; + +typedef struct rt_phy_msg rt_phy_msg_t; + + +struct rt_phy_device +{ + struct rt_device parent; + struct rt_mdio_bus *bus; + rt_uint32_t addr; + struct rt_phy_ops *ops; +}; + +typedef struct rt_phy_device rt_phy_t; + + +enum { + PHY_STATUS_OK = 0, + PHY_STATUS_FAIL, + PHY_STATUS_TIMEOUT, +}; + +typedef rt_int32_t rt_phy_status; + +struct rt_phy_ops +{ + rt_phy_status (*init)(void *object, rt_uint32_t phy_addr, rt_uint32_t src_clock_hz); + rt_phy_status (*read)(rt_uint32_t reg, rt_uint32_t *data); + rt_phy_status (*write)(rt_uint32_t reg, rt_uint32_t data); + rt_phy_status (*loopback)(rt_uint32_t mode, rt_uint32_t speed, rt_bool_t enable); + rt_phy_status (*get_link_status)(rt_bool_t *status); + rt_phy_status (*get_link_speed_duplex)(rt_uint32_t *speed, rt_uint32_t *duplex); +}; + +rt_err_t rt_hw_phy_register(struct rt_phy_device *phy, const char *name); + +#ifdef __cplusplus +} +#endif + +#endif /* __PHY_H__*/ diff --git a/components/drivers/include/drivers/phy_mdio.h b/components/drivers/include/drivers/phy_mdio.h new file mode 100644 index 0000000000..a4a79f6e7a --- /dev/null +++ b/components/drivers/include/drivers/phy_mdio.h @@ -0,0 +1,35 @@ + + +#ifndef __MDIO_H___ +#define __MDIO_H___ + +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + + +struct rt_mdio_bus_ops +{ + rt_bool_t (*init)(void *bus, rt_uint32_t src_clock_hz); + rt_size_t (*read)(void *bus, rt_uint32_t addr, rt_uint32_t reg, void *data, rt_uint32_t size); + rt_size_t (*write)(void *bus, rt_uint32_t addr, rt_uint32_t reg, void *data, rt_uint32_t size); + rt_bool_t (*uninit)(void *bus); +}; + +struct rt_mdio_bus +{ + void *hw_obj; + char *name; + struct rt_mdio_bus_ops *ops; +}; + +typedef struct rt_mdio_bus rt_mdio_t; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/components/drivers/include/rtdevice.h b/components/drivers/include/rtdevice.h index f54290097c..f0fa2f5b4a 100644 --- a/components/drivers/include/rtdevice.h +++ b/components/drivers/include/rtdevice.h @@ -69,6 +69,11 @@ extern "C" { #endif /* RT_USING_I2C_BITOPS */ #endif /* RT_USING_I2C */ +#ifdef RT_USING_PHY +#include "drivers/phy.h" +#include "drivers/phy_mdio.h" +#endif /* RT_USING_PHY */ + #ifdef RT_USING_SDIO #include "drivers/mmcsd_core.h" #include "drivers/sd.h" diff --git a/components/drivers/phy/SConscript b/components/drivers/phy/SConscript new file mode 100644 index 0000000000..ec12ed24c2 --- /dev/null +++ b/components/drivers/phy/SConscript @@ -0,0 +1,8 @@ +from building import * + +cwd = GetCurrentDir() +src = Glob('*.c') +CPPPATH = [cwd + '/../include'] +group = DefineGroup('DeviceDrivers', src, depend = ['RT_USING_PHY'], CPPPATH = CPPPATH) + +Return('group') diff --git a/components/drivers/phy/phy.c b/components/drivers/phy/phy.c new file mode 100644 index 0000000000..3ed4a1a265 --- /dev/null +++ b/components/drivers/phy/phy.c @@ -0,0 +1,78 @@ + +/* + * Copyright (c) 2006-2020, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2020-09-27 wangqiang first version + */ + +#include +#include +#include + +#define DBG_TAG "PHY" +#define DBG_LVL DBG_INFO +#include + + +static rt_size_t phy_device_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t count) +{ + struct rt_phy_device *phy = (struct rt_phy_device *)dev->user_data; + struct rt_phy_msg *msg = (struct rt_phy_msg *)buffer; + return phy->bus->ops->read(phy->bus, phy->addr, msg->reg, &(msg->value), 4); +} +static rt_size_t phy_device_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t count) +{ + struct rt_phy_device *phy = (struct rt_phy_device *)dev->user_data; + struct rt_phy_msg *msg = (struct rt_phy_msg *)buffer; + return phy->bus->ops->write(phy->bus, phy->addr, msg->reg, &(msg->value), 4); +} + + + +#ifdef RT_USING_DEVICE_OPS +const static struct rt_device_ops phy_ops = +{ + RT_NULL, + RT_NULL, + RT_NULL, + phy_device_read, + phy_device_write, + RT_NULL, +}; +#endif + +/* +* phy device register +*/ +rt_err_t rt_hw_phy_register(struct rt_phy_device *phy, const char *name) +{ + rt_err_t ret; + struct rt_device *device; + + device = &(phy->parent); + + device->type = RT_Device_Class_PHY; + device->rx_indicate = RT_NULL; + device->tx_complete = RT_NULL; + +#ifdef RT_USING_DEVICE_OPS + device->ops = phy_ops; +#else + device->init = NULL; + device->open = NULL; + device->close = NULL; + device->read = phy_device_read; + device->write = phy_device_write; + device->control = NULL; +#endif + device->user_data = phy; + + /* register a character device */ + ret = rt_device_register(device, name, RT_DEVICE_FLAG_RDWR); + + return ret; +} diff --git a/components/finsh/cmd.c b/components/finsh/cmd.c index d764ea4231..afbda59e90 100644 --- a/components/finsh/cmd.c +++ b/components/finsh/cmd.c @@ -821,6 +821,7 @@ static char *const device_type_str[] = "Miscellaneous Device", "Sensor Device", "Touch Device", + "Phy Device", "Unknown" }; diff --git a/include/rtdef.h b/include/rtdef.h index 5543b80ab7..100cd5c2d6 100644 --- a/include/rtdef.h +++ b/include/rtdef.h @@ -863,6 +863,7 @@ enum rt_device_class_type RT_Device_Class_Miscellaneous, /**< Miscellaneous device */ RT_Device_Class_Sensor, /**< Sensor device */ RT_Device_Class_Touch, /**< Touch device */ + RT_Device_Class_PHY, /**< PHY device */ RT_Device_Class_Unknown /**< unknown device */ }; -- cgit v1.3.1 From 10fb49318c45653a68555343e33cded10f5b092c Mon Sep 17 00:00:00 2001 From: WangQiang Date: Wed, 14 Oct 2020 10:27:17 +0800 Subject: 修改了一些文件头的copyright信息和Change Log MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bsp/imxrt/libraries/drivers/drv_eth.c | 1 + bsp/imxrt/libraries/peripherals/phyksz8081.c | 10 ++++++---- components/drivers/include/drivers/phy.h | 16 ++++++++++++---- components/drivers/include/drivers/phy_mdio.h | 16 ++++++++++++---- 4 files changed, 31 insertions(+), 12 deletions(-) (limited to 'components') diff --git a/bsp/imxrt/libraries/drivers/drv_eth.c b/bsp/imxrt/libraries/drivers/drv_eth.c index 5138792416..ecff2bb6ab 100644 --- a/bsp/imxrt/libraries/drivers/drv_eth.c +++ b/bsp/imxrt/libraries/drivers/drv_eth.c @@ -7,6 +7,7 @@ * Date Author Notes * 2017-10-10 Tanek the first version * 2019-5-10 misonyo add DMA TX and RX function + * 2020-10-14 wangqiang use phy device in phy monitor thread */ #include diff --git a/bsp/imxrt/libraries/peripherals/phyksz8081.c b/bsp/imxrt/libraries/peripherals/phyksz8081.c index 88c041f4d1..3735965663 100644 --- a/bsp/imxrt/libraries/peripherals/phyksz8081.c +++ b/bsp/imxrt/libraries/peripherals/phyksz8081.c @@ -1,9 +1,11 @@ /* - * Copyright (c) 2015, Freescale Semiconductor, Inc. - * Copyright 2016-2017 NXP - * All rights reserved. + * Copyright (c) 2006-2020, RT-Thread Development Team * - * SPDX-License-Identifier: BSD-3-Clause + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2020-10-14 wangqiang the first version */ #include diff --git a/components/drivers/include/drivers/phy.h b/components/drivers/include/drivers/phy.h index 9a9eaeb5dd..2d1ad9f91f 100644 --- a/components/drivers/include/drivers/phy.h +++ b/components/drivers/include/drivers/phy.h @@ -1,7 +1,15 @@ - - -#ifndef __PHY_H___ -#define __PHY_H___ +/* + * Copyright (c) 2006-2020, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2020-10-14 wangqiang the first version + */ + +#ifndef __PHY_H__ +#define __PHY_H__ #include diff --git a/components/drivers/include/drivers/phy_mdio.h b/components/drivers/include/drivers/phy_mdio.h index a4a79f6e7a..d978ec2984 100644 --- a/components/drivers/include/drivers/phy_mdio.h +++ b/components/drivers/include/drivers/phy_mdio.h @@ -1,7 +1,15 @@ - - -#ifndef __MDIO_H___ -#define __MDIO_H___ +/* + * Copyright (c) 2006-2020, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2020-10-14 wangqiang the first version + */ + +#ifndef __MDIO_H__ +#define __MDIO_H__ #include -- cgit v1.3.1 From 8d3f687abb362254df9de52245f583a4ddc4a252 Mon Sep 17 00:00:00 2001 From: 张世争 Date: Thu, 15 Oct 2020 14:37:00 +0800 Subject: add alarm flags, alarm can repeated by hour minute and second --- components/drivers/include/drivers/alarm.h | 7 +- components/drivers/rtc/alarm.c | 150 +++++++++++++++++++++++++++-- 2 files changed, 147 insertions(+), 10 deletions(-) (limited to 'components') diff --git a/components/drivers/include/drivers/alarm.h b/components/drivers/include/drivers/alarm.h index b5ebbc86d9..dd59f4c1e8 100644 --- a/components/drivers/include/drivers/alarm.h +++ b/components/drivers/include/drivers/alarm.h @@ -6,6 +6,8 @@ * Change Logs: * Date Author Notes * 2012-10-27 heyuanjie87 first version. + * 2013-05-17 aozima initial alarm event & mutex in system init. + * 2020-10-15 zhangsz add alarm flags hour minute second. */ #ifndef __ALARM_H__ @@ -22,6 +24,9 @@ #define RT_ALARM_WEEKLY 0x200 /* alarm weekly at Monday or Friday etc. */ #define RT_ALARM_MONTHLY 0x400 /* alarm monthly at someday */ #define RT_ALARM_YAERLY 0x800 /* alarm yearly at a certain date */ +#define RT_ALARM_HOUR 0x1000 /* alarm each hour at a certain min:second */ +#define RT_ALARM_MINUTE 0x2000 /* alarm each minute at a certain second */ +#define RT_ALARM_SECOND 0x4000 /* alarm each second */ /* alarm control cmd */ #define RT_ALARM_CTRL_MODIFY 1 /* modify alarm time or alarm flag */ @@ -67,6 +72,6 @@ void rt_alarm_update(rt_device_t dev, rt_uint32_t event); rt_err_t rt_alarm_delete(rt_alarm_t alarm); rt_err_t rt_alarm_start(rt_alarm_t alarm); rt_err_t rt_alarm_stop(rt_alarm_t alarm); -void rt_alarm_system_init(void); +int rt_alarm_system_init(void); #endif /* __ALARM_H__ */ diff --git a/components/drivers/rtc/alarm.c b/components/drivers/rtc/alarm.c index c497ebf727..71b6e7236a 100644 --- a/components/drivers/rtc/alarm.c +++ b/components/drivers/rtc/alarm.c @@ -7,6 +7,7 @@ * Date Author Notes * 2012-10-27 heyuanjie87 first version. * 2013-05-17 aozima initial alarm event & mutex in system init. + * 2020-10-15 zhangsz add alarm flags hour minute second. */ #include @@ -97,6 +98,61 @@ static void alarm_wakeup(struct rt_alarm *alarm, struct tm *now) } } break; + case RT_ALARM_SECOND: + { + alarm->wktime.tm_hour = now->tm_hour; + alarm->wktime.tm_min = now->tm_min; + alarm->wktime.tm_sec = alarm->wktime.tm_sec + 1; + if (alarm->wktime.tm_sec > 59) + { + alarm->wktime.tm_sec = 0; + alarm->wktime.tm_min = alarm->wktime.tm_min + 1; + if (alarm->wktime.tm_min > 59) + { + alarm->wktime.tm_min = 0; + alarm->wktime.tm_hour = alarm->wktime.tm_hour + 1; + if (alarm->wktime.tm_hour > 23) + { + alarm->wktime.tm_hour = 0; + } + } + } + wakeup = RT_TRUE; + } + break; + case RT_ALARM_MINUTE: + { + alarm->wktime.tm_hour = now->tm_hour; + if (alarm->wktime.tm_sec == now->tm_sec) + { + alarm->wktime.tm_min = alarm->wktime.tm_min + 1; + if (alarm->wktime.tm_min > 59) + { + alarm->wktime.tm_min = 0; + alarm->wktime.tm_hour = alarm->wktime.tm_hour + 1; + if (alarm->wktime.tm_hour > 23) + { + alarm->wktime.tm_hour = 0; + } + } + wakeup = RT_TRUE; + } + } + break; + case RT_ALARM_HOUR: + { + if ((alarm->wktime.tm_min == now->tm_min) && + (alarm->wktime.tm_sec == now->tm_sec)) + { + alarm->wktime.tm_hour = alarm->wktime.tm_hour + 1; + if (alarm->wktime.tm_hour > 23) + { + alarm->wktime.tm_hour = 0; + } + wakeup = RT_TRUE; + } + } + break; case RT_ALARM_DAILY: { if (((sec_now - sec_alarm) <= RT_ALARM_DELAY) && (sec_now >= sec_alarm)) @@ -177,7 +233,7 @@ static void alarm_update(rt_uint32_t event) /* calculate seconds from 00:00:00 */ sec_alarm = alarm_mkdaysec(&alarm->wktime); - if ((alarm->flag & RT_ALARM_STATE_START) && (alarm != _container.current)) + if (alarm->flag & RT_ALARM_STATE_START) { sec_tmp = sec_alarm - sec_now; if (sec_tmp > 0) @@ -212,6 +268,11 @@ static void alarm_update(rt_uint32_t event) if (alarm_set(alm_prev) == RT_EOK) _container.current = alm_prev; } + else + { + if (_container.current != RT_NULL) + alarm_set(_container.current); + } } rt_mutex_release(&_container.mutex); } @@ -279,6 +340,51 @@ static rt_err_t alarm_setup(rt_alarm_t alarm, struct tm *wktime) switch (alarm->flag & 0xFF00) { + case RT_ALARM_SECOND: + { + alarm->wktime.tm_hour = now.tm_hour; + alarm->wktime.tm_min = now.tm_min; + alarm->wktime.tm_sec = now.tm_sec + 1; + if (alarm->wktime.tm_sec > 59) + { + alarm->wktime.tm_sec = 0; + alarm->wktime.tm_min = alarm->wktime.tm_min + 1; + if (alarm->wktime.tm_min > 59) + { + alarm->wktime.tm_min = 0; + alarm->wktime.tm_hour = alarm->wktime.tm_hour + 1; + if (alarm->wktime.tm_hour > 23) + { + alarm->wktime.tm_hour = 0; + } + } + } + } + break; + case RT_ALARM_MINUTE: + { + alarm->wktime.tm_hour = now.tm_hour; + alarm->wktime.tm_min = now.tm_min + 1; + if (alarm->wktime.tm_min > 59) + { + alarm->wktime.tm_min = 0; + alarm->wktime.tm_hour = alarm->wktime.tm_hour + 1; + if (alarm->wktime.tm_hour > 23) + { + alarm->wktime.tm_hour = 0; + } + } + } + break; + case RT_ALARM_HOUR: + { + alarm->wktime.tm_hour = now.tm_hour + 1; + if (alarm->wktime.tm_hour > 23) + { + alarm->wktime.tm_hour = 0; + } + } + break; case RT_ALARM_DAILY: { /* do nothing but needed */ @@ -426,17 +532,17 @@ rt_err_t rt_alarm_start(rt_alarm_t alarm) if (alarm == RT_NULL) return (ret); rt_mutex_take(&_container.mutex, RT_WAITING_FOREVER); - if (!(alarm->flag & RT_ALARM_STATE_INITED)) + + if (!(alarm->flag & RT_ALARM_STATE_START)) { if (alarm_setup(alarm, &alarm->wktime) != RT_EOK) goto _exit; - } - if ((alarm->flag & 0x01) == RT_ALARM_STATE_STOP) - { + timestamp = time(RT_NULL); localtime_r(×tamp, &now); alarm->flag |= RT_ALARM_STATE_START; + /* set alarm */ if (_container.current == RT_NULL) { @@ -518,10 +624,10 @@ _exit: */ rt_err_t rt_alarm_delete(rt_alarm_t alarm) { - rt_err_t ret = RT_ERROR; + rt_err_t ret = RT_EOK; if (alarm == RT_NULL) - return (ret); + return RT_ERROR; rt_mutex_take(&_container.mutex, RT_WAITING_FOREVER); /* stop the alarm */ alarm->flag &= ~RT_ALARM_STATE_START; @@ -551,9 +657,11 @@ rt_alarm_t rt_alarm_create(rt_alarm_callback_t callback, struct rt_alarm_setup * if (setup == RT_NULL) return (RT_NULL); + alarm = rt_malloc(sizeof(struct rt_alarm)); if (alarm == RT_NULL) return (RT_NULL); + rt_list_init(&alarm->list); alarm->wktime = setup->wktime; @@ -586,13 +694,33 @@ static void rt_alarmsvc_thread_init(void *param) } } +void rt_alarm_dump(void) +{ + rt_list_t *next; + rt_alarm_t alarm; + rt_uint8_t index = 0; + + rt_kprintf("| alarm_id | YYYY-MM-DD hh:mm:ss | weekday | flags |\n"); + rt_kprintf("+----------+---------------------+---------+---------+\n"); + for (next = _container.head.next; next != &_container.head; next = next->next) + { + alarm = rt_list_entry(next, struct rt_alarm, list); + rt_kprintf("| No %5d | %04d-%02d-%02d %02d:%02d:%02d | %7d | 0x%04x |\n", + index++, alarm->wktime.tm_year + 1900, alarm->wktime.tm_mon + 1, alarm->wktime.tm_mday, + alarm->wktime.tm_hour, alarm->wktime.tm_min, alarm->wktime.tm_sec, + alarm->wktime.tm_wday, alarm->flag); + } + rt_kprintf("+----------+---------------------+---------+---------+\n"); +} + +FINSH_FUNCTION_EXPORT_ALIAS(rt_alarm_dump, __cmd_alarm_dump, dump alarm info); /** \brief initialize alarm service system * * \param none * \return none */ -void rt_alarm_system_init(void) +int rt_alarm_system_init(void) { rt_thread_t tid; @@ -602,8 +730,12 @@ void rt_alarm_system_init(void) tid = rt_thread_create("alarmsvc", rt_alarmsvc_thread_init, RT_NULL, - 512, 8, 1); + 2048, 10, 5); if (tid != RT_NULL) rt_thread_startup(tid); + + return 0; } + +INIT_PREV_EXPORT(rt_alarm_system_init); #endif -- cgit v1.3.1 From db0880bd2675cfb097d15147940a32e272db1c89 Mon Sep 17 00:00:00 2001 From: qiyongzhong0 <917768104@qq.com> Date: Mon, 2 Nov 2020 17:43:23 +0800 Subject: fix at_client, avoid creating the same client repeatedly and prevent working exceptions and memory leaks. --- components/net/at/src/at_client.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'components') diff --git a/components/net/at/src/at_client.c b/components/net/at/src/at_client.c index ba4009738d..788549392d 100644 --- a/components/net/at/src/at_client.c +++ b/components/net/at/src/at_client.c @@ -917,6 +917,11 @@ int at_client_init(const char *dev_name, rt_size_t recv_bufsz) RT_ASSERT(dev_name); RT_ASSERT(recv_bufsz > 0); + if (at_client_get(dev_name) != RT_NULL) + { + return result; + } + for (idx = 0; idx < AT_CLIENT_NUM_MAX && at_client_table[idx].device; idx++); if (idx >= AT_CLIENT_NUM_MAX) -- cgit v1.3.1 From 794f969d36be7368706e9aafe617649bbdece8df Mon Sep 17 00:00:00 2001 From: mysterywolf <920369182@qq.com> Date: Tue, 10 Nov 2020 12:55:21 +0800 Subject: [libc][armlibc] add readme --- components/libc/compilers/armlibc/README.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 components/libc/compilers/armlibc/README.md (limited to 'components') diff --git a/components/libc/compilers/armlibc/README.md b/components/libc/compilers/armlibc/README.md new file mode 100644 index 0000000000..8126038e46 --- /dev/null +++ b/components/libc/compilers/armlibc/README.md @@ -0,0 +1,3 @@ +## More Information + +https://www.keil.com/support/man/docs/armlib/ \ No newline at end of file -- cgit v1.3.1 From d5f88301779b943260f044a9c65b2570bf9f7b3c Mon Sep 17 00:00:00 2001 From: mysterywolf <920369182@qq.com> Date: Tue, 10 Nov 2020 13:06:16 +0800 Subject: add newlib/dlib readme --- components/libc/compilers/armlibc/README.md | 6 ++++++ components/libc/compilers/common/readme.md | 2 +- components/libc/compilers/dlib/README.md | 7 ++++++- components/libc/compilers/newlib/README.md | 9 +++++++++ 4 files changed, 22 insertions(+), 2 deletions(-) create mode 100644 components/libc/compilers/newlib/README.md (limited to 'components') diff --git a/components/libc/compilers/armlibc/README.md b/components/libc/compilers/armlibc/README.md index 8126038e46..4d2a73b6be 100644 --- a/components/libc/compilers/armlibc/README.md +++ b/components/libc/compilers/armlibc/README.md @@ -1,3 +1,9 @@ +# ARMLIB (Keil-MDK) porting for RT-Thread + +Please define RT_USING_LIBC and compile RT-Thread with Keil-MDK compiler. + + + ## More Information https://www.keil.com/support/man/docs/armlib/ \ No newline at end of file diff --git a/components/libc/compilers/common/readme.md b/components/libc/compilers/common/readme.md index 0cd56272ff..99797d933c 100644 --- a/components/libc/compilers/common/readme.md +++ b/components/libc/compilers/common/readme.md @@ -1,4 +1,4 @@ -# Attention : +## Attentions 1. This folder is "common" for armlibc newlibc and dlib. It's not "common" for minilibc. diff --git a/components/libc/compilers/dlib/README.md b/components/libc/compilers/dlib/README.md index 846eb3f5c0..acd08f9074 100644 --- a/components/libc/compilers/dlib/README.md +++ b/components/libc/compilers/dlib/README.md @@ -1,4 +1,9 @@ -Dlib(IAR) porting for RT-Thread. +# DLIB (IAR) porting for RT-Thread Please define RT_USING_LIBC and compile RT-Thread with IAR compiler. + + +## More Information + +http://www.iarsys.co.jp/download/LMS2/arm/7502/ewarm7502doc/arm/doc/EWARM_DevelopmentGuide.ENU.pdf P.130 \ No newline at end of file diff --git a/components/libc/compilers/newlib/README.md b/components/libc/compilers/newlib/README.md new file mode 100644 index 0000000000..385f329a4f --- /dev/null +++ b/components/libc/compilers/newlib/README.md @@ -0,0 +1,9 @@ +# NEWLIB (GCC) porting for RT-Thread + +Please define RT_USING_LIBC and compile RT-Thread with GCC compiler. + + + +## More Information + +https://sourceware.org/newlib/libc.html#Reentrancy \ No newline at end of file -- cgit v1.3.1