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:
Gregory Nutt 2018-05-25 12:41:44 -06:00
parent c0aef893c4
commit 548cd2892a
6 changed files with 135 additions and 19 deletions

View file

@ -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"

View file

@ -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

View file

@ -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

View file

@ -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 | \

View file

@ -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

View file

@ -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 */