Teensy 4.1 port with Ethernet support (#144)

* Start porting to Teensy 4.1, also fix some compiler warnings in FSL HAL

* Add hardware init for Teensy, refactor phy drivers, rework IMX EMAC autonegotiate code

* Revert some testing changes

* Fix incorrect phy address used outside of low_level_init_successful()

* Ethernet operational!

* Turn off DEBUG_IMX_EMAC

* Style fixes

* Style again

* Bugfix: mbed_lib.json files in project source dir were not getting picked up

* Bugfix: CLion debug configurations not generated properly due to variables going out of scope

* Support Teensy OTP MAC address
pull/15437/head
Jamie Smith 2023-03-08 20:18:33 -08:00 committed by GitHub
parent bf5be9f630
commit af6d50aefe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
31 changed files with 994 additions and 245 deletions

View File

@ -218,6 +218,8 @@ if(NOT MBED_IS_NATIVE_BUILD)
# Load upload method if one is set up
include(UploadMethodManager)
# Load debug config generator for IDEs
include(mbed_ide_debug_cfg_generator)
endif()
if(MBED_IS_NATIVE_BUILD)

View File

@ -2,7 +2,10 @@
# SPDX-License-Identifier: Apache-2.0
if("MIMXRT1050_EVK" IN_LIST MBED_TARGET_LABELS OR "MIMXRT1060_EVK" IN_LIST MBED_TARGET_LABELS)
add_subdirectory(TARGET_MIMXRT10x0_EVK)
add_subdirectory(TARGET_MIMXRT105x_EVK)
endif()
if("TEENSY_41" IN_LIST MBED_TARGET_LABELS)
add_subdirectory(TARGET_TEENSY_41)
endif()
target_include_directories(mbed-emac
@ -13,4 +16,5 @@ target_include_directories(mbed-emac
target_sources(mbed-emac
PRIVATE
imx_emac.cpp
fsl_phy_common.c
)

View File

@ -7,6 +7,8 @@
*/
#include "fsl_phy.h"
#include "ksz8081rnb_regs.h"
/*******************************************************************************
* Definitions
******************************************************************************/
@ -82,123 +84,17 @@ status_t PHY_Init(ENET_Type *base, uint32_t phyAddr, uint32_t srcClock_Hz)
}
#endif /* FSL_FEATURE_PHYKSZ8081_USE_RMII50M_MODE */
}
return result;
}
status_t PHY_AutoNegotiation(ENET_Type *base, uint32_t phyAddr)
{
status_t result = kStatus_Success;
uint32_t bssReg;
uint32_t counter = PHY_TIMEOUT_COUNT;
uint32_t timeDelay;
uint32_t ctlReg = 0;
/* Set the negotiation. */
result = PHY_Write(base, phyAddr, PHY_AUTONEG_ADVERTISE_REG,
// Enable autonegotiation, allow negotiating for all ethernet types
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;
}
}
}
}
PHY_Write(base, phyAddr, PHY_BASICCONTROL_REG, (PHY_BCTL_AUTONEG_MASK));
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;
@ -255,31 +151,6 @@ status_t PHY_EnableLoopback(ENET_Type *base, uint32_t phyAddr, phy_loop_t mode,
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);

View File

@ -0,0 +1,29 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _KSZ8081RNB_REGS_H_
#define _KSZ8081RNB_REGS_H_
/*! @brief Defines the KSZ8081-specific PHY registers. */
#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 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)
#endif

View File

@ -0,0 +1,8 @@
# Copyright (c) 2020 ARM Limited. All rights reserved.
# SPDX-License-Identifier: Apache-2.0
target_sources(mbed-emac
PRIVATE
hardware_init.cpp
fsl_phy_dp83825.c
)

View File

@ -0,0 +1,53 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _DP83825_REGS_H_
#define _DP83825_REGS_H_
/*! @brief Defines the DP83825-specific PHY registers. */
#define PHY_PHYSTS_REG 0x10 ///< Phy Status Reg
#define PHY_BISCR_REG 0x16 ///< Built-In Self Test Control Register
#define PHY_RCSR_REG 0x17 ///< Receive Clock Select Register
#define PHY_LEDCR_REG 0x18 ///< LED Control Register
#define PHY_CONTROL_ID1 0x2000U /*!< The PHY ID1*/
/*!@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)
// Bits for PHYSTS register
#define PHY_PHYSTS_DUPLEX_Msk (1 << 2)
#define PHY_PHYSTS_SPEED_Msk (1 << 1)
// Bits for BISCR register
#define PHY_BISCR_LOOPBACK_Msk (0b11111)
#define PHY_BISCR_LOOPBACK_Pos 0
#define PHY_BISCR_LOOPBACK_DIGITAL_LOOPBACK_10M_Val 0x1
#define PHY_BISCR_LOOPBACK_DIGITAL_LOOPBACK_100M_Val 0x4
#define PHY_BISCR_LOOPBACK_ANALOG_LOOPBACK_Val 0x8
// Bits for RCSR register
#define PHY_RCSR_RX_ELASTICITY_Pos 0
#define PHY_RCSR_RX_ELASTICITY_Msk 0b11
#define PHY_RCSR_RMII_CLK_SEL_Msk (1 << 7)
// Bits for LEDCR register
#define PHY_LEDCR_POLARITY_Msk (1 << 7)
#define PHY_LEDCR_BLINK_RATE_Msk (0b11 << 9)
#define PHY_LEDCR_BLINK_RATE_Pos 9
#endif

View File

@ -0,0 +1,202 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2018 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "fsl_phy.h"
#include "dp83825_regs.h"
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @brief Defines the timeout macro. */
#define PHY_TIMEOUT_COUNT 100000
/*******************************************************************************
* 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 counter = PHY_TIMEOUT_COUNT;
uint32_t idReg = 0;
status_t result = kStatus_Success;
uint32_t instance = ENET_GetInstance(base);
#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;
}
// Set up LED control for the teensy hardware.
// Reference here: https://github.com/ssilverman/QNEthernet/blob/master/src/lwip_t41.c#L265
PHY_Write(base, phyAddr, PHY_LEDCR_REG, PHY_LEDCR_POLARITY_Msk | // LED to active high
(1 << PHY_LEDCR_BLINK_RATE_Pos)); // Blink period to 10Hz
// Set up clock select register
PHY_Write(base, phyAddr, PHY_RCSR_REG, PHY_RCSR_RMII_CLK_SEL_Msk | // Select 50MHz RMII clock
(1 << PHY_RCSR_RX_ELASTICITY_Pos)); // Rx elasticity to 2 bits
// Advertise support for all Ethernet modes
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));
// Enable autonegotiation
PHY_Write(base, phyAddr, PHY_BASICCONTROL_REG,PHY_BCTL_AUTONEG_MASK);
return result;
}
status_t PHY_EnableLoopback(ENET_Type *base, uint32_t phyAddr, phy_loop_t mode, phy_speed_t speed, bool enable)
{
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;
}
PHY_Write(base, phyAddr, PHY_BASICCONTROL_REG, data);
// Per datasheet, also need to set BISCR
uint32_t biscrVal;
PHY_Read(base, phyAddr, PHY_BISCR_REG, &biscrVal);
biscrVal &= ~PHY_BISCR_LOOPBACK_Msk;
biscrVal |= (speed == kPHY_Speed100M ? PHY_BISCR_LOOPBACK_DIGITAL_LOOPBACK_100M_Val : PHY_BISCR_LOOPBACK_DIGITAL_LOOPBACK_10M_Val);
PHY_Write(base, phyAddr, PHY_BISCR_REG, biscrVal);
}
else
{
// Set requested speed manually
if (speed == kPHY_Speed100M)
{
data = PHY_BCTL_SPEED_100M_MASK | PHY_BCTL_DUPLEX_MASK;
}
else
{
data = PHY_BCTL_DUPLEX_MASK;
}
PHY_Write(base, phyAddr, PHY_BASICCONTROL_REG, data);
// Enable analog loopback in BISCR
uint32_t biscrVal;
PHY_Read(base, phyAddr, PHY_BISCR_REG, &biscrVal);
biscrVal &= ~PHY_BISCR_LOOPBACK_Msk;
biscrVal |= PHY_BISCR_LOOPBACK_ANALOG_LOOPBACK_Val;
PHY_Write(base, phyAddr, PHY_BISCR_REG, biscrVal);
}
}
else
{
/* Disable the loop mode. */
if (mode == kPHY_LocalLoop)
{
// Reenable autonegotiation
PHY_Read(base, phyAddr, PHY_BASICCONTROL_REG, &data);
data |= PHY_BCTL_RESTART_AUTONEG_MASK | PHY_BCTL_AUTONEG_MASK;
PHY_Write(base, phyAddr, PHY_BASICCONTROL_REG, (data | PHY_BCTL_RESTART_AUTONEG_MASK));
// Also, disable loopback in BISCR
uint32_t biscrVal;
PHY_Read(base, phyAddr, PHY_BISCR_REG, &biscrVal);
biscrVal &= ~PHY_BISCR_LOOPBACK_Msk;
PHY_Write(base, phyAddr, PHY_BISCR_REG, biscrVal);
}
else
{
// Reenable autonegotiation
PHY_Read(base, phyAddr, PHY_BASICCONTROL_REG, &data);
data |= PHY_BCTL_RESTART_AUTONEG_MASK | PHY_BCTL_AUTONEG_MASK;
PHY_Write(base, phyAddr, PHY_BASICCONTROL_REG, (data | PHY_BCTL_RESTART_AUTONEG_MASK));
// Disable loopback in BISCR
uint32_t biscrVal;
PHY_Read(base, phyAddr, PHY_BISCR_REG, &biscrVal);
biscrVal &= ~PHY_BISCR_LOOPBACK_Msk;
PHY_Write(base, phyAddr, PHY_BISCR_REG, biscrVal);
}
}
return kStatus_Success;
}
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 stsReg;
/* Read status register. */
result = PHY_Read(base, phyAddr, PHY_PHYSTS_REG, &stsReg);
if (result == kStatus_Success)
{
if(stsReg & PHY_PHYSTS_DUPLEX_Msk)
{
*duplex = kPHY_FullDuplex;
}
else
{
*duplex = kPHY_HalfDuplex;
}
if(stsReg & PHY_PHYSTS_SPEED_Msk)
{
*speed = kPHY_Speed10M;
}
else
{
*speed = kPHY_Speed100M;
}
}
return result;
}

View File

@ -0,0 +1,148 @@
/*
* 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_gpio.h"
#include "fsl_iomuxc.h"
#include "fsl_clock.h"
#include "mbed_wait_api.h"
#include "DigitalOut.h"
/*******************************************************************************
* Code
******************************************************************************/
static void BOARD_InitModuleClock(void)
{
const clock_enet_pll_config_t config = {true, false, 1};
CLOCK_InitEnetPll(&config);
}
extern "C" void kinetis_init_eth_hardware(void)
{
CLOCK_EnableClock(kCLOCK_Iomuxc); /* iomuxc clock (iomuxc_clk_enable): 0x03u */
// Power down pin (leave high for now, keeping the phy active)
static mbed::DigitalOut powerDown(GPIO_B0_15, 1);
// Reset pin
static mbed::DigitalOut reset(GPIO_B0_14, 1);
// Use temporary digital outputs to set the strapping options.
// Note: Cannot use GPIO pullups/pulldowns as they are not strong enough to overcome the phy's
// 10k internal pulldowns
{
mbed::DigitalOut strapPhyAdd0(GPIO_B1_04, 1);
mbed::DigitalOut strapPhyAdd1(GPIO_B1_06, 0);
mbed::DigitalOut strapRMIIMode(GPIO_B1_05, 1);
// Send reset pulse
reset.write(0);
wait_us(25); // DP83825 datasheet specifies >=25us reset pulse
reset.write(1);
wait_us(2000); // DP83825 datasheet specifies at least 2ms between reset and SMI access
}
// REF CLK (high speed output)
IOMUXC_SetPinMux(IOMUXC_GPIO_B1_10_ENET_REF_CLK, 1);
IOMUXC_SetPinConfig(IOMUXC_GPIO_B1_10_ENET_REF_CLK,
IOMUXC_SW_PAD_CTL_PAD_SRE_MASK |
IOMUXC_SW_PAD_CTL_PAD_DSE(5) |
IOMUXC_SW_PAD_CTL_PAD_SPEED(2));
// MDIO (bidirectional, open drain with 22k pullup)
IOMUXC_SetPinMux(IOMUXC_GPIO_B1_15_ENET_MDIO, 0);
IOMUXC_SetPinConfig(IOMUXC_GPIO_B1_15_ENET_MDIO,
IOMUXC_SW_PAD_CTL_PAD_SRE_MASK |
IOMUXC_SW_PAD_CTL_PAD_DSE(5) |
IOMUXC_SW_PAD_CTL_PAD_ODE_MASK |
IOMUXC_SW_PAD_CTL_PAD_PKE_MASK |
IOMUXC_SW_PAD_CTL_PAD_PUE_MASK |
IOMUXC_SW_PAD_CTL_PAD_PUS(3));
// MDC (low speed output)
IOMUXC_SetPinMux(IOMUXC_GPIO_B1_14_ENET_MDC, 0);
IOMUXC_SetPinConfig(IOMUXC_GPIO_B1_10_ENET_REF_CLK,
IOMUXC_SW_PAD_CTL_PAD_SRE_MASK |
IOMUXC_SW_PAD_CTL_PAD_DSE(5));
// RXER (input)
IOMUXC_SetPinMux(IOMUXC_GPIO_B1_11_ENET_RX_ER, 0);
IOMUXC_SetPinConfig(IOMUXC_GPIO_B1_11_ENET_RX_ER, 0);
// CRS_DV (input with 100k pulldown)
// Note: Constant is called "ENET_RX_EN" but this signal acts as CRS_DV in RMII mode
IOMUXC_SetPinMux(IOMUXC_GPIO_B1_06_ENET_RX_EN, 0);
IOMUXC_SetPinConfig(IOMUXC_GPIO_B1_06_ENET_RX_EN,
IOMUXC_SW_PAD_CTL_PAD_PKE_MASK |
IOMUXC_SW_PAD_CTL_PAD_PUE_MASK |
IOMUXC_SW_PAD_CTL_PAD_PUS(0));
// TXEN (high speed output)
IOMUXC_SetPinMux(IOMUXC_GPIO_B1_09_ENET_TX_EN, 0);
IOMUXC_SetPinConfig(IOMUXC_GPIO_B1_09_ENET_TX_EN,
IOMUXC_SW_PAD_CTL_PAD_SRE_MASK |
IOMUXC_SW_PAD_CTL_PAD_DSE(5) |
IOMUXC_SW_PAD_CTL_PAD_SPEED(3));
// TXD0 (high speed output)
IOMUXC_SetPinMux(IOMUXC_GPIO_B1_07_ENET_TX_DATA00, 0);
IOMUXC_SetPinConfig(IOMUXC_GPIO_B1_07_ENET_TX_DATA00,
IOMUXC_SW_PAD_CTL_PAD_SRE_MASK |
IOMUXC_SW_PAD_CTL_PAD_DSE(5) |
IOMUXC_SW_PAD_CTL_PAD_SPEED(3));
// TXD1 (high speed output)
IOMUXC_SetPinMux(IOMUXC_GPIO_B1_08_ENET_TX_DATA01, 0);
IOMUXC_SetPinConfig(IOMUXC_GPIO_B1_08_ENET_TX_DATA01,
IOMUXC_SW_PAD_CTL_PAD_SRE_MASK |
IOMUXC_SW_PAD_CTL_PAD_DSE(5) |
IOMUXC_SW_PAD_CTL_PAD_SPEED(3));
// RXD0 (input )
IOMUXC_SetPinMux(IOMUXC_GPIO_B1_04_ENET_RX_DATA00, 0);
IOMUXC_SetPinConfig(IOMUXC_GPIO_B1_04_ENET_RX_DATA00, 0);
// RXD1 (input)
IOMUXC_SetPinMux(IOMUXC_GPIO_B1_05_ENET_RX_DATA01, 0);
IOMUXC_SetPinConfig(IOMUXC_GPIO_B1_05_ENET_RX_DATA01, 0);
BOARD_InitModuleClock();
// Set up 50MHz clock output to the phy on GPIO_B1_10
IOMUXC_EnableMode(IOMUXC_GPR, kIOMUXC_GPR_ENET1TxClkOutputDir, true);
}
/*******************************************************************************
* EOF
******************************************************************************/

View File

@ -28,10 +28,6 @@
#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. */
@ -42,18 +38,6 @@
#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. */
@ -123,16 +107,6 @@ extern "C" {
*/
status_t PHY_Init(ENET_Type *base, uint32_t phyAddr, uint32_t srcClock_Hz);
/*!
* @brief Initiates auto negotiation.
*
* @param base ENET peripheral base address.
* @param phyAddr The PHY address.
* @retval kStatus_Success PHY auto negotiation success
* @retval kStatus_PHY_AutoNegotiateFail PHY auto negotiate fail
*/
status_t PHY_AutoNegotiation(ENET_Type *base, uint32_t phyAddr);
/*!
* @brief PHY Write function. This function write data over the SMI to
* the specified PHY register. This function is called by all PHY interfaces.
@ -187,6 +161,25 @@ status_t PHY_EnableLoopback(ENET_Type *base, uint32_t phyAddr, phy_loop_t mode,
*/
status_t PHY_GetLinkStatus(ENET_Type *base, uint32_t phyAddr, bool *status);
/*!
* @brief Gets the PHY autonegotiation status
*
* @param base ENET peripheral base address.
* @param phyAddr The PHY address.
* @param[out] status Whether autonegotiation is done.
* @return Error code or success
*/
status_t PHY_GetAutonegotiationStatus(ENET_Type *base, uint32_t phyAddr, bool *status);
/*!
* @brief Starts the autonegotiation process. Should be called after the link comes up.
*
* @param base ENET peripheral base address.
* @param phyAddr The PHY address.
* @return Error code or success
*/
status_t PHY_StartAutonegotiation(ENET_Type *base, uint32_t phyAddr);
/*!
* @brief Gets the PHY link speed and duplex.
*

View File

@ -0,0 +1,133 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2018 NXP
* All rights reserved.
*
* This file contains PHY functions which are common to all ethernet phys.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "fsl_phy.h"
#include <stdio.h>
// Timeout for waiting for the processor to execute an SMI read/write operation
#define SMI_TIMEOUT_COUNT 100000
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 = SMI_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 = SMI_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_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_GetAutonegotiationStatus(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)
{
*status = data & PHY_BSTATUS_AUTONEGCOMP_MASK;
}
return result;
}
status_t PHY_StartAutonegotiation(ENET_Type *base, uint32_t phyAddr)
{
uint32_t bmcrVal;
status_t result = PHY_Read(base, phyAddr, PHY_BASICCONTROL_REG, &bmcrVal);
bmcrVal |= PHY_BCTL_RESTART_AUTONEG_MASK;
result |= PHY_Write(base, phyAddr, PHY_BASICCONTROL_REG, bmcrVal);
return result;
}

View File

@ -34,6 +34,7 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "cmsis_os.h"
@ -43,6 +44,7 @@
#include "events/mbed_shared_queues.h"
#include "fsl_phy.h"
#include "fsl_iomuxc.h"
#include "imx_emac_config.h"
#include "imx_emac.h"
@ -73,7 +75,10 @@ extern "C" void kinetis_init_eth_hardware(void);
/** \brief Driver thread priority */
#define THREAD_PRIORITY (osPriorityNormal)
#define PHY_TASK_PERIOD 200ms
#define PHY_TASK_PERIOD 100ms
// Change to 1 to get debug printfs from the emac
#define DEBUG_IMX_EMAC 0
Kinetis_EMAC::Kinetis_EMAC() : xTXDCountSem(ENET_TX_RING_LEN, ENET_TX_RING_LEN), hwaddr()
{
@ -190,7 +195,6 @@ bool Kinetis_EMAC::low_level_init_successful()
uint32_t sysClock;
phy_speed_t phy_speed;
phy_duplex_t phy_duplex;
uint32_t phyAddr = 0;
enet_config_t config;
AT_NONCACHEABLE_SECTION_ALIGN(static enet_rx_bd_struct_t rx_desc_start_addr[ENET_RX_RING_LEN], ENET_BUFF_ALIGNMENT);
@ -228,12 +232,14 @@ bool Kinetis_EMAC::low_level_init_successful()
ENET_GetDefaultConfig(&config);
if (PHY_Init(ENET, phyAddr, sysClock) != kStatus_Success) {
if (PHY_Init(ENET, BOARD_ENET_PHY_ADDR, sysClock) != kStatus_Success)
{
printf("[IMX EMAC] Could not contact ethernet phy\n");
return false;
}
/* Get link information from PHY */
PHY_GetLinkSpeedDuplex(ENET, phyAddr, &phy_speed, &phy_duplex);
PHY_GetLinkSpeedDuplex(ENET, BOARD_ENET_PHY_ADDR, &phy_speed, &phy_duplex);
/* Change the MII speed and duplex for actual link status. */
config.miiSpeed = (enet_mii_speed_t)phy_speed;
config.miiDuplex = (enet_mii_duplex_t)phy_duplex;
@ -246,7 +252,7 @@ bool Kinetis_EMAC::low_level_init_successful()
ENET_SetCallback(&g_handle, &Kinetis_EMAC::ethernet_callback, this);
ENET_ActiveRead(ENET);
return true;
}
@ -406,7 +412,7 @@ bool Kinetis_EMAC::link_out(emac_mem_buf_t *buf)
SCB_CleanDCache_by_Addr(static_cast<uint32_t *>(memory_manager->get_ptr(buf)), memory_manager->get_len(buf));
/* Check if a descriptor is available for the transfer (wait 10ms before dropping the buffer) */
if (!xTXDCountSem.try_acquire_for(10)) {
if (!xTXDCountSem.try_acquire_for(10ms)) {
memory_manager->free(buf);
return false;
}
@ -448,44 +454,38 @@ bool Kinetis_EMAC::link_out(emac_mem_buf_t *buf)
* PHY task: monitor link
*******************************************************************************/
#define STATE_UNKNOWN (-1)
#define STATE_LINK_DOWN (0)
#define STATE_LINK_UP (1)
void Kinetis_EMAC::phy_task()
{
uint32_t phyAddr = BOARD_ENET_PHY_ADDR;
// Get current status
PHY_STATE crt_state;
bool connection_status;
PHY_GetLinkStatus(ENET, phyAddr, &connection_status);
PHY_STATE currState{};
PHY_GetLinkStatus(ENET, BOARD_ENET_PHY_ADDR, &currState.link_up);
if (connection_status) {
crt_state.connected = STATE_LINK_UP;
} else {
crt_state.connected = STATE_LINK_DOWN;
if(currState.link_up && !prev_state.link_up)
{
phy_speed_t speed;
phy_duplex_t duplex;
PHY_GetLinkSpeedDuplex(ENET, BOARD_ENET_PHY_ADDR, &speed, &duplex);
#if DEBUG_IMX_EMAC
printf("[IMX EMAC] Link went up! Negotiated for speed %s, duplex %s\n",
speed == kPHY_Speed100M ? "100M" : "10M",
duplex == kPHY_FullDuplex ? "full" : "half");
#endif
/* Poke the registers*/
ENET_SetMII(ENET, (enet_mii_speed_t)speed, (enet_mii_duplex_t)duplex);
emac_link_state_cb(currState.link_up);
}
else if(!currState.link_up && prev_state.link_up)
{
#if DEBUG_IMX_EMAC
printf("[IMX EMAC] Link went down!\n");
#endif
emac_link_state_cb(currState.link_up);
}
if (crt_state.connected == STATE_LINK_UP) {
if (prev_state.connected != STATE_LINK_UP) {
PHY_AutoNegotiation(ENET, phyAddr);
}
PHY_GetLinkSpeedDuplex(ENET, phyAddr, &crt_state.speed, &crt_state.duplex);
if (prev_state.connected != STATE_LINK_UP || crt_state.speed != prev_state.speed) {
/* Poke the registers*/
ENET_SetMII(ENET, (enet_mii_speed_t)crt_state.speed, (enet_mii_duplex_t)crt_state.duplex);
}
}
// Compare with previous state
if (crt_state.connected != prev_state.connected && emac_link_state_cb) {
emac_link_state_cb(crt_state.connected);
}
prev_state = crt_state;
prev_state = currState;
}
bool Kinetis_EMAC::power_up()
@ -505,9 +505,7 @@ bool Kinetis_EMAC::power_up()
rx_isr();
/* PHY monitoring task */
prev_state.connected = STATE_LINK_DOWN;
prev_state.speed = (phy_speed_t)STATE_UNKNOWN;
prev_state.duplex = (phy_duplex_t)STATE_UNKNOWN;
prev_state.link_up = false;
mbed::mbed_event_queue()->call(mbed::callback(this, &Kinetis_EMAC::phy_task));

View File

@ -171,9 +171,7 @@ private:
EMACMemoryManager *memory_manager; /**< Memory manager */
int phy_task_handle; /**< Handle for phy task event */
struct PHY_STATE {
int connected;
phy_speed_t speed;
phy_duplex_t duplex;
bool link_up;
};
PHY_STATE prev_state;
uint8_t hwaddr[KINETIS_HWADDR_SIZE];

View File

@ -64,6 +64,11 @@ static void _ifup()
NetworkInterface *net = NetworkInterface::get_default_instance();
TEST_ASSERT_NOT_NULL_MESSAGE(net, "No NetworkInterface configured");
nsapi_error_t err = net->connect();
if (err != NSAPI_ERROR_OK) {
printf("Failed to initialize networking. Error: %d", err);
}
TEST_ASSERT_EQUAL(NSAPI_ERROR_OK, err);
SocketAddress address;
net->get_ip_address(&address);

View File

@ -243,6 +243,7 @@ int pwmout_read_pulsewidth_us(pwmout_t *obj) {
{
count = (base->SM[module].VAL5) & PWM_VAL5_VAL5_MASK;
}
return count;
}
const PinMap *pwmout_pinmap()

View File

@ -11,7 +11,6 @@ target_include_directories(mbed-mimxrt1050-evk
target_sources(mbed-mimxrt1050-evk
INTERFACE
fsl_phy.c
fsl_flexspi_nor_boot.c
TARGET_1050_EVK/flash_api.c

View File

@ -16,4 +16,5 @@ target_include_directories(mbed-teensy-40 INTERFACE TARGET_TEENSY_40)
# Target for Teensy 4.1
add_library(mbed-teensy-41 INTERFACE)
target_link_libraries(mbed-teensy-41 INTERFACE
mbed-teensy-4x)
mbed-teensy-4x)
target_include_directories(mbed-teensy-41 INTERFACE TARGET_TEENSY_41)

View File

@ -15,7 +15,7 @@
* limitations under the License.
*/
/* MBED TARGET LIST: MIMXRT1050_EVK */
/* MBED TARGET LIST: TEENSY_40 */
#ifndef MBED_PINNAMES_H
#define MBED_PINNAMES_H

View File

@ -0,0 +1,273 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2013 ARM Limited
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* MBED TARGET LIST: TEENSY_41 */
#ifndef MBED_PINNAMES_H
#define MBED_PINNAMES_H
#include "cmsis.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef enum {
PIN_INPUT,
PIN_OUTPUT
} PinDirection;
#define GPIO_PORT_SHIFT 12
#define GPIO_MUX_PORT 5
typedef enum {
WAKEUP = ((5 << GPIO_PORT_SHIFT) | 0),
PMIC_ON_REQ = ((5 << GPIO_PORT_SHIFT) | 1),
PMIC_STBY_REQ = ((5 << GPIO_PORT_SHIFT) | 2),
GPIO_EMC_00 = ((4 << GPIO_PORT_SHIFT) | 0),
GPIO_EMC_01 = ((4 << GPIO_PORT_SHIFT) | 1),
GPIO_EMC_02 = ((4 << GPIO_PORT_SHIFT) | 2),
GPIO_EMC_03 = ((4 << GPIO_PORT_SHIFT) | 3),
GPIO_EMC_04 = ((4 << GPIO_PORT_SHIFT) | 4),
GPIO_EMC_05 = ((4 << GPIO_PORT_SHIFT) | 5),
GPIO_EMC_06 = ((4 << GPIO_PORT_SHIFT) | 6),
GPIO_EMC_07 = ((4 << GPIO_PORT_SHIFT) | 7),
GPIO_EMC_08 = ((4 << GPIO_PORT_SHIFT) | 8),
GPIO_EMC_09 = ((4 << GPIO_PORT_SHIFT) | 9),
GPIO_EMC_10 = ((4 << GPIO_PORT_SHIFT) | 10),
GPIO_EMC_11 = ((4 << GPIO_PORT_SHIFT) | 11),
GPIO_EMC_12 = ((4 << GPIO_PORT_SHIFT) | 12),
GPIO_EMC_13 = ((4 << GPIO_PORT_SHIFT) | 13),
GPIO_EMC_14 = ((4 << GPIO_PORT_SHIFT) | 14),
GPIO_EMC_15 = ((4 << GPIO_PORT_SHIFT) | 15),
GPIO_EMC_16 = ((4 << GPIO_PORT_SHIFT) | 16),
GPIO_EMC_17 = ((4 << GPIO_PORT_SHIFT) | 17),
GPIO_EMC_18 = ((4 << GPIO_PORT_SHIFT) | 18),
GPIO_EMC_19 = ((4 << GPIO_PORT_SHIFT) | 19),
GPIO_EMC_20 = ((4 << GPIO_PORT_SHIFT) | 20),
GPIO_EMC_21 = ((4 << GPIO_PORT_SHIFT) | 21),
GPIO_EMC_22 = ((4 << GPIO_PORT_SHIFT) | 22),
GPIO_EMC_23 = ((4 << GPIO_PORT_SHIFT) | 23),
GPIO_EMC_24 = ((4 << GPIO_PORT_SHIFT) | 24),
GPIO_EMC_25 = ((4 << GPIO_PORT_SHIFT) | 25),
GPIO_EMC_26 = ((4 << GPIO_PORT_SHIFT) | 26),
GPIO_EMC_27 = ((4 << GPIO_PORT_SHIFT) | 27),
GPIO_EMC_28 = ((4 << GPIO_PORT_SHIFT) | 28),
GPIO_EMC_29 = ((4 << GPIO_PORT_SHIFT) | 29),
GPIO_EMC_30 = ((4 << GPIO_PORT_SHIFT) | 30),
GPIO_EMC_31 = ((4 << GPIO_PORT_SHIFT) | 31),
GPIO_EMC_32 = ((3 << GPIO_PORT_SHIFT) | 18),
GPIO_EMC_33 = ((3 << GPIO_PORT_SHIFT) | 19),
GPIO_EMC_34 = ((3 << GPIO_PORT_SHIFT) | 20),
GPIO_EMC_35 = ((3 << GPIO_PORT_SHIFT) | 21),
GPIO_EMC_36 = ((3 << GPIO_PORT_SHIFT) | 22),
GPIO_EMC_37 = ((3 << GPIO_PORT_SHIFT) | 23),
GPIO_EMC_38 = ((3 << GPIO_PORT_SHIFT) | 24),
GPIO_EMC_39 = ((3 << GPIO_PORT_SHIFT) | 25),
GPIO_EMC_40 = ((3 << GPIO_PORT_SHIFT) | 26),
GPIO_EMC_41 = ((3 << GPIO_PORT_SHIFT) | 27),
GPIO_AD_B0_00 = ((1 << GPIO_PORT_SHIFT) | 0),
GPIO_AD_B0_01 = ((1 << GPIO_PORT_SHIFT) | 1),
GPIO_AD_B0_02 = ((1 << GPIO_PORT_SHIFT) | 2),
GPIO_AD_B0_03 = ((1 << GPIO_PORT_SHIFT) | 3),
GPIO_AD_B0_04 = ((1 << GPIO_PORT_SHIFT) | 4),
GPIO_AD_B0_05 = ((1 << GPIO_PORT_SHIFT) | 5),
GPIO_AD_B0_06 = ((1 << GPIO_PORT_SHIFT) | 6),
GPIO_AD_B0_07 = ((1 << GPIO_PORT_SHIFT) | 7),
GPIO_AD_B0_08 = ((1 << GPIO_PORT_SHIFT) | 8),
GPIO_AD_B0_09 = ((1 << GPIO_PORT_SHIFT) | 9),
GPIO_AD_B0_10 = ((1 << GPIO_PORT_SHIFT) | 10),
GPIO_AD_B0_11 = ((1 << GPIO_PORT_SHIFT) | 11),
GPIO_AD_B0_12 = ((1 << GPIO_PORT_SHIFT) | 12),
GPIO_AD_B0_13 = ((1 << GPIO_PORT_SHIFT) | 13),
GPIO_AD_B0_14 = ((1 << GPIO_PORT_SHIFT) | 14),
GPIO_AD_B0_15 = ((1 << GPIO_PORT_SHIFT) | 15),
GPIO_AD_B1_00 = ((1 << GPIO_PORT_SHIFT) | 16),
GPIO_AD_B1_01 = ((1 << GPIO_PORT_SHIFT) | 17),
GPIO_AD_B1_02 = ((1 << GPIO_PORT_SHIFT) | 18),
GPIO_AD_B1_03 = ((1 << GPIO_PORT_SHIFT) | 19),
GPIO_AD_B1_04 = ((1 << GPIO_PORT_SHIFT) | 20),
GPIO_AD_B1_05 = ((1 << GPIO_PORT_SHIFT) | 21),
GPIO_AD_B1_06 = ((1 << GPIO_PORT_SHIFT) | 22),
GPIO_AD_B1_07 = ((1 << GPIO_PORT_SHIFT) | 23),
GPIO_AD_B1_08 = ((1 << GPIO_PORT_SHIFT) | 24),
GPIO_AD_B1_09 = ((1 << GPIO_PORT_SHIFT) | 25),
GPIO_AD_B1_10 = ((1 << GPIO_PORT_SHIFT) | 26),
GPIO_AD_B1_11 = ((1 << GPIO_PORT_SHIFT) | 27),
GPIO_AD_B1_12 = ((1 << GPIO_PORT_SHIFT) | 28),
GPIO_AD_B1_13 = ((1 << GPIO_PORT_SHIFT) | 29),
GPIO_AD_B1_14 = ((1 << GPIO_PORT_SHIFT) | 30),
GPIO_AD_B1_15 = ((1 << GPIO_PORT_SHIFT) | 31),
GPIO_B0_00 = ((2 << GPIO_PORT_SHIFT) | 0),
GPIO_B0_01 = ((2 << GPIO_PORT_SHIFT) | 1),
GPIO_B0_02 = ((2 << GPIO_PORT_SHIFT) | 2),
GPIO_B0_03 = ((2 << GPIO_PORT_SHIFT) | 3),
GPIO_B0_04 = ((2 << GPIO_PORT_SHIFT) | 4),
GPIO_B0_05 = ((2 << GPIO_PORT_SHIFT) | 5),
GPIO_B0_06 = ((2 << GPIO_PORT_SHIFT) | 6),
GPIO_B0_07 = ((2 << GPIO_PORT_SHIFT) | 7),
GPIO_B0_08 = ((2 << GPIO_PORT_SHIFT) | 8),
GPIO_B0_09 = ((2 << GPIO_PORT_SHIFT) | 9),
GPIO_B0_10 = ((2 << GPIO_PORT_SHIFT) | 10),
GPIO_B0_11 = ((2 << GPIO_PORT_SHIFT) | 11),
GPIO_B0_12 = ((2 << GPIO_PORT_SHIFT) | 12),
GPIO_B0_13 = ((2 << GPIO_PORT_SHIFT) | 13),
GPIO_B0_14 = ((2 << GPIO_PORT_SHIFT) | 14),
GPIO_B0_15 = ((2 << GPIO_PORT_SHIFT) | 15),
GPIO_B1_00 = ((2 << GPIO_PORT_SHIFT) | 16),
GPIO_B1_01 = ((2 << GPIO_PORT_SHIFT) | 17),
GPIO_B1_02 = ((2 << GPIO_PORT_SHIFT) | 18),
GPIO_B1_03 = ((2 << GPIO_PORT_SHIFT) | 19),
GPIO_B1_04 = ((2 << GPIO_PORT_SHIFT) | 20),
GPIO_B1_05 = ((2 << GPIO_PORT_SHIFT) | 21),
GPIO_B1_06 = ((2 << GPIO_PORT_SHIFT) | 22),
GPIO_B1_07 = ((2 << GPIO_PORT_SHIFT) | 23),
GPIO_B1_08 = ((2 << GPIO_PORT_SHIFT) | 24),
GPIO_B1_09 = ((2 << GPIO_PORT_SHIFT) | 25),
GPIO_B1_10 = ((2 << GPIO_PORT_SHIFT) | 26),
GPIO_B1_11 = ((2 << GPIO_PORT_SHIFT) | 27),
GPIO_B1_12 = ((2 << GPIO_PORT_SHIFT) | 28),
GPIO_B1_13 = ((2 << GPIO_PORT_SHIFT) | 29),
GPIO_B1_14 = ((2 << GPIO_PORT_SHIFT) | 30),
GPIO_B1_15 = ((2 << GPIO_PORT_SHIFT) | 31),
GPIO_SD_B0_00 = ((3 << GPIO_PORT_SHIFT) | 12),
GPIO_SD_B0_01 = ((3 << GPIO_PORT_SHIFT) | 13),
GPIO_SD_B0_02 = ((3 << GPIO_PORT_SHIFT) | 14),
GPIO_SD_B0_03 = ((3 << GPIO_PORT_SHIFT) | 15),
GPIO_SD_B0_04 = ((3 << GPIO_PORT_SHIFT) | 16),
GPIO_SD_B0_05 = ((3 << GPIO_PORT_SHIFT) | 17),
GPIO_SD_B1_00 = ((3 << GPIO_PORT_SHIFT) | 0),
GPIO_SD_B1_01 = ((3 << GPIO_PORT_SHIFT) | 1),
GPIO_SD_B1_02 = ((3 << GPIO_PORT_SHIFT) | 2),
GPIO_SD_B1_03 = ((3 << GPIO_PORT_SHIFT) | 3),
GPIO_SD_B1_04 = ((3 << GPIO_PORT_SHIFT) | 4),
GPIO_SD_B1_05 = ((3 << GPIO_PORT_SHIFT) | 5),
GPIO_SD_B1_06 = ((3 << GPIO_PORT_SHIFT) | 6),
GPIO_SD_B1_07 = ((3 << GPIO_PORT_SHIFT) | 7),
GPIO_SD_B1_08 = ((3 << GPIO_PORT_SHIFT) | 8),
GPIO_SD_B1_09 = ((3 << GPIO_PORT_SHIFT) | 9),
GPIO_SD_B1_10 = ((3 << GPIO_PORT_SHIFT) | 10),
GPIO_SD_B1_11 = ((3 << GPIO_PORT_SHIFT) | 11),
// Teensy 4.1 pin names -------------------------------------
// Digital
D0 = GPIO_AD_B0_03,
D1 = GPIO_AD_B0_02,
D2 = GPIO_EMC_04,
D3 = GPIO_EMC_05,
D4 = GPIO_EMC_06,
D5 = GPIO_EMC_08,
D6 = GPIO_B0_10,
D7 = GPIO_B1_01,
D8 = GPIO_B1_00,
D9 = GPIO_B0_11,
D10 = GPIO_B0_00,
D11 = GPIO_B0_02,
D12 = GPIO_B0_01,
D13 = GPIO_B0_03,
D14 = GPIO_AD_B1_02,
D15 = GPIO_AD_B1_03,
D16 = GPIO_AD_B1_07,
D17 = GPIO_AD_B1_06,
D18 = GPIO_AD_B1_01,
D19 = GPIO_AD_B1_00,
D20 = GPIO_AD_B1_10,
D21 = GPIO_AD_B1_11,
D22 = GPIO_AD_B1_08,
D23 = GPIO_AD_B1_09,
D24 = GPIO_AD_B0_12,
D25 = GPIO_AD_B0_13,
D26 = GPIO_AD_B1_14,
D27 = GPIO_AD_B1_15,
D28 = GPIO_EMC_32,
D29 = GPIO_EMC_31,
D30 = GPIO_EMC_37,
D31 = GPIO_EMC_36,
D32 = GPIO_B0_12,
D33 = GPIO_EMC_07, // note: All above here are the same as TEENSY4_0
D34 = GPIO_B1_13,
D35 = GPIO_B1_12,
D36 = GPIO_B1_02,
D37 = GPIO_B1_07,
D38 = GPIO_AD_B1_12,
D39 = GPIO_AD_B1_13,
D40 = GPIO_AD_B1_04,
D41 = GPIO_AD_B1_05,
// Analog
A0 = GPIO_AD_B1_02,
A1 = GPIO_AD_B1_03,
A2 = GPIO_AD_B1_07,
A3 = GPIO_AD_B1_06,
A4 = GPIO_AD_B1_01,
A5 = GPIO_AD_B1_00,
A6 = GPIO_AD_B1_10,
A7 = GPIO_AD_B1_11,
A8 = GPIO_AD_B1_08,
A9 = GPIO_AD_B1_09,
A10 = GPIO_AD_B0_12,
A11 = GPIO_AD_B0_13,
A12 = GPIO_AD_B1_14,
A13 = GPIO_AD_B1_15,
A14 = GPIO_AD_B1_12,
A15 = GPIO_AD_B1_13,
A16 = GPIO_AD_B1_04,
A17 = GPIO_AD_B1_05,
// SD card pins
SD_CLK = GPIO_SD_B0_01,
SD_DAT0 = GPIO_SD_B0_02,
SD_DAT1 = GPIO_SD_B0_03,
SD_DAT2 = GPIO_SD_B0_04,
SD_DAT3 = GPIO_SD_B0_05,
// Standard aliases -------------------------------------
// Even though the UART console is not used by default, we still provide mappings on the standard Arduino pins
CONSOLE_TX = D1,
CONSOLE_RX = D0,
// Not connected
NC = (int)0xFFFFFFFF
} PinName;
// Standardized LED and button names
#define LED1 D13
#define USER_LED LED1
typedef enum {
PullNone = 0,
PullDown = 1,
PullUp_47K = 2,
PullUp_100K = 3,
PullUp_22K = 4,
PullDefault = PullUp_47K,
PullUp = PullUp_47K
} PinMode;
#ifdef __cplusplus
}
#endif
#endif

View File

@ -25,6 +25,9 @@
to be as vector table */
#undef __VECTOR_TABLE
// Set to 1 by MIMXRT pullups/pulldowns on CRS_DV and RXD0
#define BOARD_ENET_PHY_ADDR 1
#include "objects.h"
#endif

View File

@ -96,7 +96,7 @@ static dcp_context_t s_dcpContextSwitchingBuffer;
static void dcp_reverse_and_copy(uint8_t *src, uint8_t *dest, size_t src_len)
{
for (int i = 0; i < src_len; i++)
for (size_t i = 0; i < src_len; i++)
{
dest[i] = src[src_len - 1 - i];
}

View File

@ -762,7 +762,7 @@ static void ENET_SetTxBufferDescriptors(enet_handle_t *handle,
/* Check the input parameters. */
for (ringNum = 0; ringNum < config->ringNum; ringNum++)
{
if (buffCfg->txBdStartAddrAlign > 0)
if (buffCfg->txBdStartAddrAlign != 0)
{
volatile enet_tx_bd_struct_t *curBuffDescrip = buffCfg->txBdStartAddrAlign;
txBuffSizeAlign = buffCfg->txBuffSizeAlign;
@ -780,7 +780,7 @@ static void ENET_SetTxBufferDescriptors(enet_handle_t *handle,
/* Sets the crc. */
curBuffDescrip->control = ENET_BUFFDESCRIPTOR_TX_TRANMITCRC_MASK;
/* Sets the last buffer descriptor with the wrap flag. */
if (count == buffCfg->txBdNumber - 1)
if (count == (uint32_t)(buffCfg->txBdNumber - 1))
{
curBuffDescrip->control |= ENET_BUFFDESCRIPTOR_TX_WRAP_MASK;
}
@ -811,7 +811,7 @@ static void ENET_SetRxBufferDescriptors(enet_handle_t *handle,
/* Default single ring is supported. */
uint8_t ringNum;
uint32_t count;
uint32_t rxBuffSizeAlign;
uint32_t __attribute__((unused)) rxBuffSizeAlign;
uint8_t *rxBuffer;
const enet_buffer_config_t *buffCfg = bufferConfig;
#ifdef ENET_ENHANCEDBUFFERDESCRIPTOR_MODE
@ -835,7 +835,7 @@ static void ENET_SetRxBufferDescriptors(enet_handle_t *handle,
#endif /* FSL_FEATURE_ENET_QUEUE > 1 */
#endif /* ENET_ENHANCEDBUFFERDESCRIPTOR_MODE */
if ((buffCfg->rxBdStartAddrAlign > 0) && (buffCfg->rxBufferAlign > 0))
if ((buffCfg->rxBdStartAddrAlign != 0) && (buffCfg->rxBufferAlign != 0))
{
volatile enet_rx_bd_struct_t *curBuffDescrip = buffCfg->rxBdStartAddrAlign;
rxBuffSizeAlign = buffCfg->rxBuffSizeAlign;
@ -859,7 +859,7 @@ static void ENET_SetRxBufferDescriptors(enet_handle_t *handle,
/* Initializes the buffer descriptors with empty bit. */
curBuffDescrip->control = ENET_BUFFDESCRIPTOR_RX_EMPTY_MASK;
/* Sets the last buffer descriptor with the wrap flag. */
if (count == buffCfg->rxBdNumber - 1)
if (count == (uint32_t)(buffCfg->rxBdNumber - 1))
{
curBuffDescrip->control |= ENET_BUFFDESCRIPTOR_RX_WRAP_MASK;
}

View File

@ -200,7 +200,7 @@ status_t FLEXRAM_AllocateRam(flexram_allocate_ram_t *config)
continue;
}
if (i < (dtcmBankNum + ocramBankNum + itcmBankNum))
if (i < (uint32_t)(dtcmBankNum + ocramBankNum + itcmBankNum))
{
bankCfg |= ((uint32_t)kFLEXRAM_BankITCM) << (i * 2);
continue;

View File

@ -97,11 +97,6 @@ static FLEXSPI_Type *const s_flexspiBases[] = FLEXSPI_BASE_PTRS;
/*! @brief Pointers to flexspi IRQ number for each instance. */
static const IRQn_Type s_flexspiIrqs[] = FLEXSPI_IRQS;
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
/* Clock name array */
static const clock_ip_name_t s_flexspiClock[] = FLEXSPI_CLOCKS;
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
#if defined(FSL_DRIVER_TRANSFER_DOUBLE_WEAK_IRQ) && FSL_DRIVER_TRANSFER_DOUBLE_WEAK_IRQ
/*! @brief Pointers to flexspi handles for each instance. */
static flexspi_handle_t *s_flexspiHandle[ARRAY_SIZE(s_flexspiBases)];
@ -245,9 +240,8 @@ void FLEXSPI_Init(FLEXSPI_Type *base, const flexspi_config_t *config)
uint8_t i = 0;
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
/* Enable the flexspi clock */
//CLOCK_EnableClock(s_flexspiClock[FLEXSPI_GetInstance(base)]);
/* Access the register directly to avoid warnings accessing non ran functions */
/* Enable the flexspi clock. */
/* Do this by accessing the register directly to avoid warnings accessing non-RAM functions */
CCM->CCGR6 |= CCM_CCGR6_CG5_MASK;
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */

View File

@ -1395,7 +1395,7 @@ void SAI_TxSetConfig(I2S_Type *base, sai_transceiver_t *config)
config->channelMask = 1U << config->startChannel;
}
for (i = 0U; i < FSL_FEATURE_SAI_CHANNEL_COUNTn(base); i++)
for (i = 0U; i < (uint32_t)FSL_FEATURE_SAI_CHANNEL_COUNTn(base); i++)
{
if (((uint32_t)1 << i) & config->channelMask)
{
@ -1408,7 +1408,7 @@ void SAI_TxSetConfig(I2S_Type *base, sai_transceiver_t *config)
config->endChannel = i;
}
}
assert(channelNums <= FSL_FEATURE_SAI_CHANNEL_COUNTn(base));
assert(channelNums <= (uint32_t)FSL_FEATURE_SAI_CHANNEL_COUNTn(base));
config->channelNums = channelNums;
#if defined(FSL_FEATURE_SAI_HAS_FIFO_COMBINE_MODE) && (FSL_FEATURE_SAI_HAS_FIFO_COMBINE_MODE)
/* make sure combine mode disabled while multipe channel is used */
@ -1518,7 +1518,7 @@ void SAI_RxSetConfig(I2S_Type *base, sai_transceiver_t *config)
config->channelMask = 1U << config->startChannel;
}
for (i = 0U; i < FSL_FEATURE_SAI_CHANNEL_COUNTn(base); i++)
for (i = 0U; i < (uint32_t)FSL_FEATURE_SAI_CHANNEL_COUNTn(base); i++)
{
if (((uint32_t)1 << i) & config->channelMask)
{
@ -1531,7 +1531,7 @@ void SAI_RxSetConfig(I2S_Type *base, sai_transceiver_t *config)
config->endChannel = i;
}
}
assert(channelNums <= FSL_FEATURE_SAI_CHANNEL_COUNTn(base));
assert(channelNums <= (uint32_t)FSL_FEATURE_SAI_CHANNEL_COUNTn(base));
config->channelNums = channelNums;
#if defined(FSL_FEATURE_SAI_HAS_FIFO_COMBINE_MODE) && (FSL_FEATURE_SAI_HAS_FIFO_COMBINE_MODE)
/* make sure combine mode disabled while multipe channel is used */
@ -1851,7 +1851,7 @@ void SAI_TxSetFormat(I2S_Type *base,
}
/* if channel nums is not set, calculate it here according to channelMask*/
for (i = 0U; i < FSL_FEATURE_SAI_CHANNEL_COUNTn(base); i++)
for (i = 0U; i < (uint32_t)FSL_FEATURE_SAI_CHANNEL_COUNTn(base); i++)
{
if (((uint32_t)1 << i) & format->channelMask)
{
@ -1990,7 +1990,7 @@ void SAI_RxSetFormat(I2S_Type *base,
}
/* if channel nums is not set, calculate it here according to channelMask*/
for (i = 0U; i < FSL_FEATURE_SAI_CHANNEL_COUNTn(base); i++)
for (i = 0U; i < (uint32_t)FSL_FEATURE_SAI_CHANNEL_COUNTn(base); i++)
{
if (((uint32_t)1 << i) & format->channelMask)
{
@ -2087,7 +2087,7 @@ void SAI_WriteMultiChannelBlocking(
bytesPerWord = (size_t)((FSL_FEATURE_SAI_FIFO_COUNT - base->TCR1) * bytesPerWord);
#endif
for (i = 0U; (i < FSL_FEATURE_SAI_CHANNEL_COUNTn(base)); i++)
for (i = 0U; (i < (uint32_t)FSL_FEATURE_SAI_CHANNEL_COUNTn(base)); i++)
{
if ((1U << i) & (channelMask))
{
@ -2096,7 +2096,7 @@ void SAI_WriteMultiChannelBlocking(
}
}
assert(channelNums <= FSL_FEATURE_SAI_CHANNEL_COUNTn(base));
assert(channelNums <= (uint32_t)FSL_FEATURE_SAI_CHANNEL_COUNTn(base));
bytesPerWord *= channelNums;
while (j < size)
@ -2140,7 +2140,7 @@ void SAI_ReadMultiChannelBlocking(
#if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1)
bytesPerWord = (size_t)(base->RCR1 * bytesPerWord);
#endif
for (i = 0U; (i < FSL_FEATURE_SAI_CHANNEL_COUNTn(base)); i++)
for (i = 0U; (i < (uint32_t)FSL_FEATURE_SAI_CHANNEL_COUNTn(base)); i++)
{
if ((1U << i) & (channelMask))
{
@ -2149,7 +2149,7 @@ void SAI_ReadMultiChannelBlocking(
}
}
assert(channelNums <= FSL_FEATURE_SAI_CHANNEL_COUNTn(base));
assert(channelNums <= (uint32_t)FSL_FEATURE_SAI_CHANNEL_COUNTn(base));
bytesPerWord *= channelNums;
while (j < size)

View File

@ -289,6 +289,8 @@ void mbed_mac_address(char *mac) {
}
uint8_t mbed_otp_mac_address(char *mac) {
#if TARGET_MIMXRT1050_EVK
/* Check if a valid MAC address is programmed to the fuse bank */
if ((OCOTP->MAC0 != 0) &&
(OCOTP->MAC1 != 0) &&
@ -308,10 +310,26 @@ uint8_t mbed_otp_mac_address(char *mac) {
mac[3] = MAC[1];
mac[4] = MAC[2] >> 8;
mac[5] = MAC[2];
} else {
return 0;
return 1;
}
return 1;
#endif
#if TARGET_TEENSY_4X
if(OCOTP->MAC0 != 0 || OCOTP->MAC1 != 0)
{
mac[0] = OCOTP->MAC1 >> 8;
mac[1] = OCOTP->MAC1 >> 0;
mac[2] = OCOTP->MAC0 >> 24;
mac[3] = OCOTP->MAC0 >> 16;
mac[4] = OCOTP->MAC0 >> 8;
mac[5] = OCOTP->MAC0 >> 0;
return 1;
}
#endif
return 0;
}
void mbed_default_mac_address(char *mac) {

View File

@ -5195,6 +5195,24 @@
"EMAC"
]
},
"TEENSY_41": {
"inherits": [
"MIMXRT105X"
],
"extra_labels_add": [
"TEENSY_4X",
"TEENSY_41"
],
"macros_add": [
"MIMXRT105X_BOARD_HAS_EXTERNAL_RAM=0",
"MBED_APP_SIZE=0x7C0000"
],
"overrides": {
"console-usb": true,
"console-uart": false,
"network-default-interface-type": "ETHERNET"
}
},
"MIMXRT1170_EVK": {
"supported_form_factors": [
"ARDUINO_UNO"

View File

@ -82,7 +82,4 @@ if(EXISTS ${CMAKE_CURRENT_LIST_DIR}/../../${EXPECTED_MBED_UPLOAD_CFG_FILE_PATH})
else()
message(STATUS "Mbed: Target does not have any upload method configuration. 'make flash-' commands will not be available unless configured by the upper-level project.")
set(UPLOAD_METHOD_DEFAULT "NONE")
endif()
# Load debug config generator for IDEs
include(mbed_ide_debug_cfg_generator)
endif()

View File

@ -97,6 +97,7 @@ if(MBED_NEED_TO_RECONFIGURE)
-m "${MBED_TARGET}"
--mbed-os-path ${CMAKE_CURRENT_LIST_DIR}/../..
--output-dir ${CMAKE_CURRENT_BINARY_DIR}
--program-path ${CMAKE_SOURCE_DIR}
${APP_CONFIG_ARGUMENT}
${CUSTOM_TARGET_ARGUMENT})

View File

@ -34,12 +34,12 @@ endif()
if(MBED_GENERATE_CLION_DEBUG_CFGS)
# Find CLion run config dir
set(CLION_RUN_CONF_DIR ${CMAKE_SOURCE_DIR}/.idea/runConfigurations)
file(MAKE_DIRECTORY ${CLION_RUN_CONF_DIR})
function(mbed_generate_ide_debug_configuration CMAKE_TARGET)
# Find CLion run config dir
set(CLION_RUN_CONF_DIR ${CMAKE_SOURCE_DIR}/.idea/runConfigurations)
file(MAKE_DIRECTORY ${CLION_RUN_CONF_DIR})
# Create name (combine target name, Mbed target, and build type to generate a unique string)
set(CONFIG_NAME "GDB ${CMAKE_TARGET} ${MBED_TARGET} ${CMAKE_BUILD_TYPE}")
set(RUN_CONF_PATH "${CLION_RUN_CONF_DIR}/${CONFIG_NAME}.xml")
@ -95,8 +95,6 @@ if(MBED_GENERATE_CLION_DEBUG_CFGS)
# -------------------------------------------------------------
elseif(MBED_GENERATE_VS_CODE_DEBUG_CFGS)
set(VSCODE_LAUNCH_JSON_PATH ${CMAKE_SOURCE_DIR}/.vscode/launch.json)
# Start building up json file. Needs to be a global property so we can append to it from anywhere.
# Note: Cannot use a cache variable for this because cache variables aren't allowed to contain newlines.
set_property(GLOBAL PROPERTY VSCODE_LAUNCH_JSON_CONTENT
@ -167,6 +165,7 @@ elseif(MBED_GENERATE_VS_CODE_DEBUG_CFGS)
# Take all generated debug configurations and write them to launch.json.
function(mbed_finalize_ide_debug_configurations)
set(VSCODE_LAUNCH_JSON_PATH ${CMAKE_SOURCE_DIR}/.vscode/launch.json)
# Add footer
set_property(GLOBAL APPEND_STRING PROPERTY VSCODE_LAUNCH_JSON_CONTENT "