Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions arch/arm/src/arm_m/arm_hardfault.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include <string.h>
#include <assert.h>
#include <debug.h>
#include <syslog.h>

#include <nuttx/userspace.h>
#include <arch/irq.h>
Expand Down Expand Up @@ -182,6 +183,24 @@ int arm_hardfault(int irq, void *context, void *arg)
}
#endif

/* Surface the SCB fault status and the stacked PC/LR unconditionally:
* this image executes from QSPI XIP and intermittent hard faults carry
* no other evidence of the failing access.
*/

syslog(LOG_ALERT,
"HARDFAULT: CFSR=%08" PRIx32 " HFSR=%08" PRIx32
" BFAR=%08" PRIx32 " MMFAR=%08" PRIx32 "\n",
cfsr, hfsr, getreg32(NVIC_BFAULT_ADDR),
getreg32(NVIC_MEMMANAGE_ADDR));
if (context != NULL)
{
syslog(LOG_ALERT,
"HARDFAULT: stacked PC=%08" PRIx32 " LR=%08" PRIx32 "\n",
((FAR uint32_t *)context)[REG_PC],
((FAR uint32_t *)context)[REG_R14]);
}

up_irq_save();
PANIC_WITH_REGS("panic", context);
return OK;
Expand Down
7 changes: 7 additions & 0 deletions arch/arm/src/stm32h7/stm32_allocateheap.c
Original file line number Diff line number Diff line change
Expand Up @@ -423,7 +423,14 @@ void arm_addregion(void)
#ifdef BOARD_SDRAM2_SIZE
if (mm_regions < CONFIG_MM_REGIONS)
{
#ifdef BOARD_SDRAM2_HEAP_OFFSET
static_assert(BOARD_SDRAM2_HEAP_OFFSET < BOARD_SDRAM2_SIZE,
"SDRAM2 heap offset exceeds the available SDRAM");
addregion (STM32_FMC_BANK6 + BOARD_SDRAM2_HEAP_OFFSET,
BOARD_SDRAM2_SIZE - BOARD_SDRAM2_HEAP_OFFSET, "SDRAM2");
#else
addregion (STM32_FMC_BANK6, BOARD_SDRAM2_SIZE, "SDRAM2");
#endif
mm_regions++;
}
#endif
Expand Down
229 changes: 228 additions & 1 deletion arch/arm/src/stm32h7/stm32_ethernet.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
#include <arpa/inet.h>

#include <nuttx/arch.h>
#include <nuttx/clock.h>
#include <nuttx/queue.h>
#include <nuttx/wdog.h>
#include <nuttx/wqueue.h>
Expand All @@ -65,6 +66,11 @@

#include <arch/board/board.h>

#ifdef BOARD_ETH_PHY_POLL
# define STM32_LINK_POLL_DELAY MSEC2TICK(500)
# define STM32_LINK_DEBOUNCE 2
#endif

/* STM32H7_NETHERNET determines the number of physical interfaces that can
* be supported by the hardware. CONFIG_STM32H7_ETHMAC will defined if
* any STM32H7 Ethernet support is enabled in the configuration.
Expand Down Expand Up @@ -612,6 +618,13 @@ struct stm32_ethmac_s
struct wdog_s txtimeout; /* TX timeout timer */
struct work_s irqwork; /* For deferring interrupt work to the work queue */
struct work_s pollwork; /* For deferring poll work to the work queue */
#ifdef BOARD_ETH_PHY_POLL
struct work_s linkwork; /* For polling the PHY link state */
uint8_t linksamples; /* Number of matching PHY samples */
bool linkstate; /* Last published PHY link state */
bool linkcandidate;
bool linkerror; /* MDIO failure already reported */
#endif

/* This holds the information visible to the NuttX network */

Expand Down Expand Up @@ -756,6 +769,10 @@ static int stm32_phywrite(uint16_t phydevaddr, uint16_t phyregaddr,
static inline int stm32_dm9161(struct stm32_ethmac_s *priv);
#endif
static int stm32_phyinit(struct stm32_ethmac_s *priv);
#ifdef BOARD_ETH_PHY_POLL
static int stm32_phylinkread(bool *linkup);
static void stm32_link_work(void *arg);
#endif
#ifdef CONFIG_STM32H7_ETHMAC_REGDEBUG
static void stm32_phyregdump(void);
#endif
Expand Down Expand Up @@ -2417,6 +2434,11 @@ static int stm32_ifup(struct net_driver_s *dev)
struct stm32_ethmac_s *priv = (struct stm32_ethmac_s *)dev->d_private;
int ret;

if (priv->ifup)
{
return OK;
}

#ifdef CONFIG_NET_IPv4
ninfo("Bringing up: %u.%u.%u.%u\n",
ip4_addr1(dev->d_ipaddr), ip4_addr2(dev->d_ipaddr),
Expand All @@ -2443,6 +2465,32 @@ static int stm32_ifup(struct net_driver_s *dev)
up_enable_irq(STM32_IRQ_ETH);

stm32_checksetup();
#ifdef BOARD_ETH_PHY_POLL
ret = stm32_phylinkread(&priv->linkstate);
if (ret < 0 || !priv->linkstate)
{
priv->linkstate = false;
netdev_carrier_off(dev);
}
else
{
netdev_carrier_on(dev);
}

priv->linkcandidate = priv->linkstate;
priv->linksamples = 0;
priv->linkerror = false;
ret = work_queue(LPWORK, &priv->linkwork, stm32_link_work, priv,
STM32_LINK_POLL_DELAY);
if (ret < 0)
{
nerr("ERROR: Failed to schedule PHY link work: %d\n", ret);
stm32_ifdown(dev);
return ret;
}
#else
netdev_carrier_on(dev);
#endif
return OK;
}

Expand Down Expand Up @@ -2471,6 +2519,16 @@ static int stm32_ifdown(struct net_driver_s *dev)

/* Disable the Ethernet interrupt */

priv->ifup = false;
#ifdef BOARD_ETH_PHY_POLL
work_cancel(LPWORK, &priv->linkwork);
priv->linkstate = false;
priv->linkcandidate = false;
priv->linksamples = 0;
priv->linkerror = false;
#endif
netdev_carrier_off(dev);

flags = enter_critical_section();
up_disable_irq(STM32_IRQ_ETH);

Expand All @@ -2487,7 +2545,6 @@ static int stm32_ifdown(struct net_driver_s *dev)

/* Mark the device "down" */

priv->ifup = false;
leave_critical_section(flags);
return OK;
}
Expand Down Expand Up @@ -3363,6 +3420,18 @@ static int stm32_phyinit(struct stm32_ethmac_s *priv)
/* Perform auto-negotiation if so configured */

#ifdef CONFIG_STM32H7_AUTONEG
#ifdef BOARD_ETH_PHY_POLL
/* Start auto-negotiation even when booting without a cable. */

ret = stm32_phywrite(CONFIG_STM32H7_PHYADDR, MII_MCR,
MII_MCR_ANENABLE, MII_MCR_ANENABLE);
if (ret < 0)
{
nerr("ERROR: Failed to enable auto-negotiation: %d\n", ret);
return ret;
}
#endif

/* Wait for link status */

for (timeout = 0; timeout < PHY_RETRY_TIMEOUT; timeout++)
Expand All @@ -3384,7 +3453,12 @@ static int stm32_phyinit(struct stm32_ethmac_s *priv)
if (timeout >= PHY_RETRY_TIMEOUT)
{
nerr("ERROR: Timed out waiting for link status: %04x\n", phyval);
#ifdef BOARD_ETH_PHY_POLL
ninfo("Continuing with carrier off until PHY polling finds a link\n");
return OK;
#else
return -ETIMEDOUT;
#endif
}

/* Enable auto-negotiation */
Expand Down Expand Up @@ -3524,6 +3598,157 @@ static int stm32_phyinit(struct stm32_ethmac_s *priv)
return OK;
}

#ifdef BOARD_ETH_PHY_POLL
/****************************************************************************
* Function: stm32_phylinkread
*
* Description:
* Read the PHY link state. MII_MSR link status is latch-low, so the
* register must be read twice to obtain the current value.
*
****************************************************************************/

static int stm32_phylinkread(bool *linkup)
{
uint16_t phyval;
int ret;

ret = stm32_phyread(CONFIG_STM32H7_PHYADDR, MII_MSR, &phyval);
if (ret < 0)
{
return ret;
}

ret = stm32_phyread(CONFIG_STM32H7_PHYADDR, MII_MSR, &phyval);
if (ret >= 0)
{
*linkup = (phyval & MII_MSR_LINKSTATUS) != 0;
}

return ret;
}

/****************************************************************************
* Function: stm32_maclinkconfig
*
* Description:
* Synchronize the MAC speed and duplex bits after PHY auto-negotiation.
*
****************************************************************************/

static void stm32_maclinkconfig(struct stm32_ethmac_s *priv)
{
uint32_t regval;
uint32_t enabled;

regval = stm32_getreg(STM32_ETH_MACCR);
enabled = regval & (ETH_MACCR_RE | ETH_MACCR_TE);
regval &= ~(ETH_MACCR_RE | ETH_MACCR_TE | ETH_MACCR_DM |
ETH_MACCR_FES);
stm32_putreg(regval, STM32_ETH_MACCR);

if (priv->fduplex)
{
regval |= ETH_MACCR_DM;
}

if (priv->mbps100)
{
regval |= ETH_MACCR_FES;
}

stm32_putreg(regval | enabled, STM32_ETH_MACCR);
}

/****************************************************************************
* Function: stm32_link_work
*
* Description:
* Poll and debounce the external PHY link state from LPWORK.
*
****************************************************************************/

static void stm32_link_work(void *arg)
{
struct stm32_ethmac_s *priv = (struct stm32_ethmac_s *)arg;
bool linkup;
int ret;

net_lock();
if (!priv->ifup)
{
net_unlock();
return;
}

ret = stm32_phylinkread(&linkup);
if (ret < 0)
{
if (!priv->linkerror)
{
nwarn("WARNING: Failed to read PHY link state: %d\n", ret);
priv->linkerror = true;
}

goto reschedule;
}

if (priv->linkerror)
{
ninfo("PHY link status reads recovered\n");
priv->linkerror = false;
}

if (linkup != priv->linkcandidate)
{
priv->linkcandidate = linkup;
priv->linksamples = 1;
}
else if (priv->linksamples < STM32_LINK_DEBOUNCE)
{
priv->linksamples++;
}

if (priv->linksamples >= STM32_LINK_DEBOUNCE &&
linkup != priv->linkstate)
{
if (linkup)
{
ret = stm32_phyinit(priv);
if (ret < 0 || stm32_phylinkread(&linkup) < 0 || !linkup)
{
goto reschedule;
}

stm32_maclinkconfig(priv);
priv->linkstate = true;
netdev_carrier_on(&priv->dev);
ninfo("PHY link is up\n");
}
else
{
wd_cancel(&priv->txtimeout);
priv->linkstate = false;
netdev_carrier_off(&priv->dev);
ninfo("PHY link is down\n");
}
}

reschedule:
if (priv->ifup)
{
ret = work_queue(LPWORK, &priv->linkwork, stm32_link_work, priv,
STM32_LINK_POLL_DELAY);
if (ret < 0)
{
nwarn("WARNING: Failed to reschedule PHY link work: %d\n", ret);
}
}

net_unlock();
}
#endif

#endif

/****************************************************************************
Expand Down Expand Up @@ -3651,8 +3876,10 @@ static inline void stm32_ethgpioconfig(struct stm32_ethmac_s *priv)
* MII_RX_ER, MII_RX_DV, MII_CRS, MII_COL, MDC, MDIO
*/

# ifndef BOARD_ETH_MII_NO_CRS_COL
stm32_configgpio(GPIO_ETH_MII_COL);
stm32_configgpio(GPIO_ETH_MII_CRS);
# endif
stm32_configgpio(GPIO_ETH_MII_RXD0);
stm32_configgpio(GPIO_ETH_MII_RXD1);
stm32_configgpio(GPIO_ETH_MII_RXD2);
Expand Down
Loading
Loading