mirror of
https://github.com/apache/nuttx.git
synced 2026-08-05 14:19:03 +00:00
arch/arm/src/imxrt and configs/imxrt1050-evk: Add PHY access support needed to support the network monitor. Cannot enable it yet... I am getting hardfaults when I enable the PHY interrupt.
This commit is contained in:
parent
c0aef893c4
commit
548cd2892a
6 changed files with 135 additions and 19 deletions
|
|
@ -73,6 +73,7 @@ config IMXRT_ENET
|
|||
bool "Ethernet"
|
||||
default n
|
||||
select ARCH_HAVE_PHY
|
||||
select ARCH_PHY_INTERRUPT
|
||||
select ARCH_HAVE_NETDEV_STATISTICS
|
||||
|
||||
menu "FlexIO Peripherals"
|
||||
|
|
|
|||
|
|
@ -56,6 +56,7 @@
|
|||
#include <nuttx/signal.h>
|
||||
#include <nuttx/net/mii.h>
|
||||
#include <nuttx/net/arp.h>
|
||||
#include <nuttx/net/phy.h>
|
||||
#include <nuttx/net/netdev.h>
|
||||
|
||||
#ifdef CONFIG_NET_PKT
|
||||
|
|
@ -334,6 +335,9 @@ static int imxrt_ioctl(struct net_driver_s *dev, int cmd,
|
|||
|
||||
/* PHY/MII support */
|
||||
|
||||
#if defined(CONFIG_NETDEV_PHY_IOCTL) && defined(CONFIG_ARCH_PHY_INTERRUPT)
|
||||
static int imxrt_phyintenable(struct imxrt_driver_s *priv);
|
||||
#endif
|
||||
static inline void imxrt_initmii(struct imxrt_driver_s *priv);
|
||||
static int imxrt_writemii(struct imxrt_driver_s *priv, uint8_t phyaddr,
|
||||
uint8_t regaddr, uint16_t data);
|
||||
|
|
@ -644,9 +648,9 @@ static inline void imxrt_dispatch(FAR struct imxrt_driver_s *priv)
|
|||
pkt_input(&priv->dev);
|
||||
#endif
|
||||
|
||||
/* We only accept IP packets of the configured type and ARP packets */
|
||||
|
||||
#ifdef CONFIG_NET_IPv4
|
||||
/* Check for an IPv4 packet */
|
||||
|
||||
if (BUF->type == HTONS(ETHTYPE_IP))
|
||||
{
|
||||
ninfo("IPv4 frame\n");
|
||||
|
|
@ -688,6 +692,8 @@ static inline void imxrt_dispatch(FAR struct imxrt_driver_s *priv)
|
|||
else
|
||||
#endif
|
||||
#ifdef CONFIG_NET_IPv6
|
||||
/* Check for an IPv6 packet */
|
||||
|
||||
if (BUF->type == HTONS(ETHTYPE_IP6))
|
||||
{
|
||||
ninfo("Iv6 frame\n");
|
||||
|
|
@ -726,6 +732,8 @@ static inline void imxrt_dispatch(FAR struct imxrt_driver_s *priv)
|
|||
else
|
||||
#endif
|
||||
#ifdef CONFIG_NET_ARP
|
||||
/* Check for an ARP packet */
|
||||
|
||||
if (BUF->type == htons(ETHTYPE_ARP))
|
||||
{
|
||||
NETDEV_RXARP(&priv->dev);
|
||||
|
|
@ -1544,6 +1552,22 @@ static int imxrt_ioctl(struct net_driver_s *dev, int cmd, unsigned long arg)
|
|||
switch (cmd)
|
||||
{
|
||||
#ifdef CONFIG_NETDEV_PHY_IOCTL
|
||||
#ifdef CONFIG_ARCH_PHY_INTERRUPT
|
||||
case SIOCMIINOTIFY: /* Set up for PHY event notifications */
|
||||
{
|
||||
struct mii_iotcl_notify_s *req = (struct mii_iotcl_notify_s *)((uintptr_t)arg);
|
||||
|
||||
ret = phy_notify_subscribe(dev->d_ifname, req->pid, req->signo, req->arg);
|
||||
if (ret == OK)
|
||||
{
|
||||
/* Enable PHY link up/down interrupts */
|
||||
|
||||
ret = imxrt_phyintenable(priv);
|
||||
}
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
case SIOCGMIIPHY: /* Get MII PHY address */
|
||||
{
|
||||
struct mii_ioctl_data_s *req =
|
||||
|
|
@ -1568,7 +1592,7 @@ static int imxrt_ioctl(struct net_driver_s *dev, int cmd, unsigned long arg)
|
|||
ret = imxrt_writemii(priv, req->phy_id, req->reg_num, req->val_in);
|
||||
}
|
||||
break;
|
||||
#endif /* ifdef CONFIG_NETDEV_PHY_IOCTL */
|
||||
#endif /* CONFIG_NETDEV_PHY_IOCTL */
|
||||
|
||||
default:
|
||||
ret = -ENOTTY;
|
||||
|
|
@ -1579,6 +1603,54 @@ static int imxrt_ioctl(struct net_driver_s *dev, int cmd, unsigned long arg)
|
|||
}
|
||||
#endif /* CONFIG_NETDEV_IOCTL */
|
||||
|
||||
/****************************************************************************
|
||||
* Function: imxrt_phyintenable
|
||||
*
|
||||
* Description:
|
||||
* Enable link up/down PHY interrupts. The interrupt protocol is like this:
|
||||
*
|
||||
* - Interrupt status is cleared when the interrupt is enabled.
|
||||
* - Interrupt occurs. Interrupt is disabled (at the processor level) when
|
||||
* is received.
|
||||
* - Interrupt status is cleared when the interrupt is re-enabled.
|
||||
*
|
||||
* Input Parameters:
|
||||
* priv - A reference to the private driver state structure
|
||||
*
|
||||
* Returned Value:
|
||||
* OK on success; Negated errno (-ETIMEDOUT) on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#if defined(CONFIG_NETDEV_PHY_IOCTL) && defined(CONFIG_ARCH_PHY_INTERRUPT)
|
||||
static int imxrt_phyintenable(struct imxrt_driver_s *priv)
|
||||
{
|
||||
#if defined(CONFIG_ETH0_PHY_KSZ8051) || defined(CONFIG_ETH0_PHY_KSZ8061) || \
|
||||
defined(CONFIG_ETH0_PHY_KSZ8081)
|
||||
uint16_t phyval;
|
||||
int ret;
|
||||
|
||||
/* Read the interrupt status register in order to clear any pending
|
||||
* interrupts
|
||||
*/
|
||||
|
||||
ret = imxrt_readmii(priv, priv->phyaddr, MII_KSZ8081_INT, &phyval);
|
||||
if (ret == OK)
|
||||
{
|
||||
/* Enable link up/down interrupts */
|
||||
|
||||
ret = imxrt_writemii(priv, priv->phyaddr, MII_KSZ8081_INT,
|
||||
(MII_KSZ80x1_INT_LDEN | MII_KSZ80x1_INT_LUEN));
|
||||
}
|
||||
|
||||
return ret;
|
||||
#else
|
||||
# error Unrecognized PHY
|
||||
return -ENOSYS;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Function: imxrt_initmii
|
||||
*
|
||||
|
|
@ -2238,7 +2310,6 @@ int imxrt_netinitialize(int intf)
|
|||
mac[3] = (uidl & 0x00ff0000) >> 16;
|
||||
mac[4] = (uidl & 0x0000ff00) >> 8;
|
||||
mac[5] = (uidl & 0x000000ff);
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_IMXRT_ENET_PHYINIT
|
||||
|
|
|
|||
|
|
@ -186,6 +186,31 @@ Configuration sub-directories
|
|||
|
||||
Or, disable IPv4 support so that only IPv4 addressing is used.
|
||||
|
||||
3. The network monitor is not enabled in this configuration. As a
|
||||
result, the Ethernet cable must be connected when the board is
|
||||
powered up. Otherwise, it will stall for a long period of time
|
||||
before the NSH prompt appears and you will not be able to used
|
||||
the board.
|
||||
|
||||
The following configuration options should be added to your
|
||||
configuration in order to use the network monitor:
|
||||
|
||||
CONFIG_IMXRT_ENET_PHYINIT=y
|
||||
CONFIG_IMXRT_GPIO1_0_15_IRQ=y
|
||||
CONFIG_IMXRT_GPIO_IRQ=y
|
||||
CONFIG_NETDEV_IOCTL=y
|
||||
CONFIG_NETDEV_PHY_IOCTL=y
|
||||
CONFIG_NSH_NETINIT_MONITOR=y
|
||||
CONFIG_NSH_NETINIT_RETRYMSEC=2000
|
||||
CONFIG_NSH_NETINIT_SIGNO=18
|
||||
CONFIG_NSH_NETINIT_THREAD=y
|
||||
CONFIG_NSH_NETINIT_THREAD_PRIORITY=80
|
||||
CONFIG_NSH_NETINIT_THREAD_STACKSIZE=1568
|
||||
|
||||
STATUS: As of this writing, I get a hardfault when I enable the PHY
|
||||
interrupt so I suspect that there is something incorrect in that
|
||||
pin configuration.
|
||||
|
||||
nsh:
|
||||
|
||||
Configures the NuttShell (nsh) located at examples/nsh. This NSH
|
||||
|
|
|
|||
|
|
@ -96,16 +96,24 @@
|
|||
#define GPIO_SW8 (GPIO_INTERRUPT | GPIO_INT_FALLINGEDGE | \
|
||||
GPIO_PORT5 | GPIO_PIN0 | IOMUX_SW8)
|
||||
|
||||
/* GPIOAD_B0_10 */
|
||||
/* Ethernet Interrupt: GPIOAD_B0_10
|
||||
*
|
||||
* This pin has a week pull-up within the PHY, is open-drain, and requires
|
||||
* an external 1k ohm pull-up resistor (present on the EVK). A falling
|
||||
* edge then indicates a change in state of the PHY.
|
||||
*/
|
||||
|
||||
#define IOMUX_ENET_INT (IOMUX_SLEW_FAST | IOMUX_DRIVE_50OHM | \
|
||||
IOMUX_SPEED_MEDIUM | IOMUX_PULL_UP_100K | \
|
||||
_IOMUX_PULL_ENABLE)
|
||||
#define GPIO_ENET_INT (GPIO_OUTPUT | GPIO_OUTPUT_ONE | \
|
||||
IOMUX_SPEED_MEDIUM | IOMUX_PULL_UP_100K)
|
||||
#define GPIO_ENET_INT (GPIO_INTERRUPT | GPIO_INT_FALLINGEDGE | \
|
||||
GPIO_PORT1 | GPIO_PIN10 | IOMUX_ENET_INT)
|
||||
#define GPIO_ENET_IRQ IMXRT_IRQ_GPIO1_10
|
||||
|
||||
/* GPIOAD_B0_09 */
|
||||
/* Ethernet Reset: GPIOAD_B0_09
|
||||
*
|
||||
* The #RST uses inverted logic. The initial value of zero will put the
|
||||
* PHY into the reset state.
|
||||
*/
|
||||
|
||||
#define IOMUX_ENET_RST (IOMUX_SLEW_FAST | IOMUX_DRIVE_50OHM | \
|
||||
IOMUX_SPEED_MEDIUM | IOMUX_PULL_UP_100K | \
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@
|
|||
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <nuttx/irq.h>
|
||||
|
|
@ -129,7 +130,7 @@ static void imxrt_enet_phy_enable(bool enable)
|
|||
*
|
||||
************************************************************************************/
|
||||
|
||||
void weak_function imxrt_phy_boardinitialize(void)
|
||||
int imxrt_phy_boardinitialize(int intf)
|
||||
{
|
||||
#ifdef CONFIG_IMXRT_GPIO1_0_15_IRQ
|
||||
/* Configure the PHY interrupt pin */
|
||||
|
|
@ -138,10 +139,19 @@ void weak_function imxrt_phy_boardinitialize(void)
|
|||
imxrt_config_gpio(GPIO_ENET_INT);
|
||||
#endif
|
||||
|
||||
/* Configure the PHY reset pin. This will also take the PHY out of reset. */
|
||||
/* Configure the PHY reset pin.
|
||||
*
|
||||
* The #RST uses inverted logic. The initial value of zero will put the
|
||||
* PHY into the reset state.
|
||||
*/
|
||||
|
||||
phyinfo("Configuring reset: %08x\n", GPIO_ENET_RST);
|
||||
imxrt_config_gpio(GPIO_ENET_RST);
|
||||
|
||||
/* Take the PHY out of reset. */
|
||||
|
||||
imxrt_gpio_write(GPIO_ENET_RST, true);
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
|
@ -211,7 +221,6 @@ int arch_phy_irq(FAR const char *intf, xcpt_t handler, void *arg,
|
|||
phy_enable_t *enable)
|
||||
{
|
||||
irqstate_t flags;
|
||||
gpio_pinset_t pinset;
|
||||
phy_enable_t enabler;
|
||||
int irq;
|
||||
|
||||
|
|
@ -222,15 +231,13 @@ int arch_phy_irq(FAR const char *intf, xcpt_t handler, void *arg,
|
|||
|
||||
if (strcmp(intf, IMXRT_ENET_DEVNAME) == 0)
|
||||
{
|
||||
phyinfo("Select EMAC\n");
|
||||
pinset = GPIO_ENET_INT;
|
||||
irq = GPIO_ENET_IRQ;
|
||||
enabler = imxrt_enet_phy_enable;
|
||||
irq = GPIO_ENET_IRQ;
|
||||
enabler = imxrt_enet_phy_enable;
|
||||
}
|
||||
else
|
||||
{
|
||||
nerr("ERROR: Unsupported interface: %s\n", intf);
|
||||
return NULL;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Disable interrupts until we are done. This guarantees that the
|
||||
|
|
|
|||
|
|
@ -404,9 +404,9 @@ static void skel_receive(FAR struct skel_driver_s *priv)
|
|||
pkt_input(&priv->sk_dev);
|
||||
#endif
|
||||
|
||||
/* We only accept IP packets of the configured type and ARP packets */
|
||||
|
||||
#ifdef CONFIG_NET_IPv4
|
||||
/* Check for an IPv4 packet */
|
||||
|
||||
if (BUF->type == HTONS(ETHTYPE_IP))
|
||||
{
|
||||
ninfo("IPv4 frame\n");
|
||||
|
|
@ -426,6 +426,8 @@ static void skel_receive(FAR struct skel_driver_s *priv)
|
|||
else
|
||||
#endif
|
||||
#ifdef CONFIG_NET_IPv6
|
||||
/* Check for an IPv6 packet */
|
||||
|
||||
if (BUF->type == HTONS(ETHTYPE_IP6))
|
||||
{
|
||||
ninfo("Iv6 frame\n");
|
||||
|
|
@ -442,6 +444,8 @@ static void skel_receive(FAR struct skel_driver_s *priv)
|
|||
else
|
||||
#endif
|
||||
#ifdef CONFIG_NET_ARP
|
||||
/* Check for an ARP packet */
|
||||
|
||||
if (BUF->type == htons(ETHTYPE_ARP))
|
||||
{
|
||||
/* Dispatch ARP packet to the network layer */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue