9
0
Fork 0

STM32 Ethernet... initial bring-up changes

git-svn-id: https://nuttx.svn.sourceforge.net/svnroot/nuttx/trunk@4165 7fd9a85b-ad96-42d3-883c-3090e2eb8679
This commit is contained in:
patacongo 2011-12-12 15:59:33 +00:00
parent 1374e6868f
commit 3da009b2e7
5 changed files with 323 additions and 72 deletions

View File

@ -256,10 +256,19 @@ int tftpget(const char *remote, const char *local, in_addr_t addr, bool binary)
/* Parse the incoming DATA packet */ /* Parse the incoming DATA packet */
if (nbytesrecvd < TFTP_DATAHEADERSIZE || if (nbytesrecvd < TFTP_DATAHEADERSIZE)
tftp_parsedatapacket(packet, &opcode, &rblockno) != OK || {
/* Packet is not big enough to be parsed */
nvdbg("Tiny data packet ignored\n");
continue;
}
if (tftp_parsedatapacket(packet, &opcode, &rblockno) != OK ||
blockno != rblockno) blockno != rblockno)
{ {
/* Opcode is not TFTP_DATA or the block number is unexpected */
nvdbg("Parse failure\n"); nvdbg("Parse failure\n");
if (opcode > TFTP_MAXRFC1350) if (opcode > TFTP_MAXRFC1350)
{ {

View File

@ -2253,3 +2253,5 @@
* arch/arm/src/stm32/chip/stm32_eth.h: Add Ethernet register definitions * arch/arm/src/stm32/chip/stm32_eth.h: Add Ethernet register definitions
for the STM32 F4. for the STM32 F4.
* arch/arm/srcm/stm32/stm32_eth.c: Adds an Ethernet driver for the STM32 F4. * arch/arm/srcm/stm32/stm32_eth.c: Adds an Ethernet driver for the STM32 F4.
* arch/arm/srcm/stm32/stm32_dac.c and stm32_adc.c: "Skeleton" files for STM32
DAC and ADC drivers. The actual logic will come later.

View File

@ -169,6 +169,14 @@
#define STM32_ETH_NFREEBUFFERS (CONFIG_STM32_ETH_NTXDESC+1) #define STM32_ETH_NFREEBUFFERS (CONFIG_STM32_ETH_NTXDESC+1)
/* Extremely detailed register debug that you would normally never want
* enabled.
*/
#ifndef CONFIG_DEBUG
# undef CONFIG_STM32_ETHMAC_REGDEBUG
#endif
/* Clocking *****************************************************************/ /* Clocking *****************************************************************/
/* Set MACMIIAR CR bits depending on HCLK setting */ /* Set MACMIIAR CR bits depending on HCLK setting */
@ -525,6 +533,18 @@ static struct stm32_ethmac_s g_stm32ethmac[STM32_NETHERNET];
/**************************************************************************** /****************************************************************************
* Private Function Prototypes * Private Function Prototypes
****************************************************************************/ ****************************************************************************/
/* Register operations ******************************************************/
#if defined(CONFIG_STM32_ETHMAC_REGDEBUG) && defined(CONFIG_DEBUG)
static uint32_t stm32_getreg(uint32_t addr);
static void stm32_putreg(uint32_t val, uint32_t addr);
static void stm32_checksetup(void);
#else
# define stm32_getreg(addr) getreg16(addr)
# define stm32_putreg(val,addr) putreg16(val,addr)
# define stm32_checksetup()
#endif
/* Free buffer management */ /* Free buffer management */
static void stm32_initbuffer(FAR struct stm32_ethmac_s *priv); static void stm32_initbuffer(FAR struct stm32_ethmac_s *priv);
@ -585,6 +605,125 @@ static int stm32_ethconfig(FAR struct stm32_ethmac_s *priv);
/**************************************************************************** /****************************************************************************
* Private Functions * Private Functions
****************************************************************************/ ****************************************************************************/
/****************************************************************************
* Name: stm32_getreg
*
* Description:
* This function may to used to intercept an monitor all register accesses.
* Clearly this is nothing you would want to do unless you are debugging
* this driver.
*
* Input Parameters:
* addr - The register address to read
*
* Returned Value:
* The value read from the register
*
****************************************************************************/
#if defined(CONFIG_STM32_ETHMAC_REGDEBUG) && defined(CONFIG_DEBUG)
static uint32_t stm32_getreg(uint32_t addr)
{
static uint32_t prevaddr = 0;
static uint32_t preval = 0;
static uint32_t count = 0;
/* Read the value from the register */
uint32_t val = getreg32(addr);
/* Is this the same value that we read from the same register last time?
* Are we polling the register? If so, suppress some of the output.
*/
if (addr == prevaddr && val == preval)
{
if (count == 0xffffffff || ++count > 3)
{
if (count == 4)
{
lldbg("...\n");
}
return val;
}
}
/* No this is a new address or value */
else
{
/* Did we print "..." for the previous value? */
if (count > 3)
{
/* Yes.. then show how many times the value repeated */
lldbg("[repeats %d more times]\n", count-3);
}
/* Save the new address, value, and count */
prevaddr = addr;
preval = val;
count = 1;
}
/* Show the register value read */
lldbg("%08x->%08x\n", addr, val);
return val;
}
#endif
/****************************************************************************
* Name: stm32_putreg
*
* Description:
* This function may to used to intercept an monitor all register accesses.
* Clearly this is nothing you would want to do unless you are debugging
* this driver.
*
* Input Parameters:
* val - The value to write to the register
* addr - The register address to read
*
* Returned Value:
* None
*
****************************************************************************/
#if defined(CONFIG_STM32_ETHMAC_REGDEBUG) && defined(CONFIG_DEBUG)
static void stm32_putreg(uint32_t val, uint32_t addr)
{
/* Show the register value being written */
lldbg("%08x<-%08x\n", addr, val);
/* Write the value */
putreg32(val, addr);
}
#endif
/****************************************************************************
* Name: stm32_checksetup
*
* Description:
* Show the state of critical configuration registers.
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
****************************************************************************/
#if defined(CONFIG_STM32_ETHMAC_REGDEBUG) && defined(CONFIG_DEBUG)
static void stm32_checksetup(void)
{
}
#endif
/**************************************************************************** /****************************************************************************
* Function: stm32_initbuffer * Function: stm32_initbuffer
@ -609,8 +748,12 @@ static void stm32_initbuffer(FAR struct stm32_ethmac_s *priv)
uint8_t *buffer; uint8_t *buffer;
int i; int i;
/* Initialize the head of the free buffer list */
sq_init(&priv->freeb); sq_init(&priv->freeb);
/* Add all of the pre-allocated buffers to the free buffer list */
for (i = 0, buffer = priv->alloc; for (i = 0, buffer = priv->alloc;
i < STM32_ETH_NFREEBUFFERS; i < STM32_ETH_NFREEBUFFERS;
i++, buffer += CONFIG_STM32_ETH_BUFSIZE) i++, buffer += CONFIG_STM32_ETH_BUFSIZE)
@ -640,6 +783,8 @@ static void stm32_initbuffer(FAR struct stm32_ethmac_s *priv)
static inline uint8_t *stm32_allocbuffer(FAR struct stm32_ethmac_s *priv) static inline uint8_t *stm32_allocbuffer(FAR struct stm32_ethmac_s *priv)
{ {
/* Allocate a buffer by returning the head of the free buffer list */
return (uint8_t *)sq_remfirst(&priv->freeb); return (uint8_t *)sq_remfirst(&priv->freeb);
} }
@ -665,6 +810,8 @@ static inline uint8_t *stm32_allocbuffer(FAR struct stm32_ethmac_s *priv)
static inline void stm32_freebuffer(FAR struct stm32_ethmac_s *priv, uint8_t *buffer) static inline void stm32_freebuffer(FAR struct stm32_ethmac_s *priv, uint8_t *buffer)
{ {
/* Free the buffer by adding it to to the end of the free buffer list */
sq_addlast((FAR sq_entry_t *)buffer, &priv->freeb); sq_addlast((FAR sq_entry_t *)buffer, &priv->freeb);
} }
@ -688,6 +835,8 @@ static inline void stm32_freebuffer(FAR struct stm32_ethmac_s *priv, uint8_t *bu
static inline bool stm32_isfreebuffer(FAR struct stm32_ethmac_s *priv) static inline bool stm32_isfreebuffer(FAR struct stm32_ethmac_s *priv)
{ {
/* Return TRUE if the free buffer list is not empty */
return !sq_empty(&priv->freeb); return !sq_empty(&priv->freeb);
} }
@ -734,11 +883,15 @@ static int stm32_transmit(FAR struct stm32_ethmac_s *priv)
*/ */
txdesc = priv->txhead; txdesc = priv->txhead;
nllvdbg("d_len: %d txhead: %08x tdes0: %08x\n", txdesc, txdesc->tdes0);
DEBUGASSERT(txdesc && (txdesc->tdes0 & ETH_TDES0_OWN) == 0); DEBUGASSERT(txdesc && (txdesc->tdes0 & ETH_TDES0_OWN) == 0);
/* Is the size to be sent greater than the size of the Ethernet buffer? */ /* Is the size to be sent greater than the size of the Ethernet buffer? */
#if CONFIG_NET_BUFSIZE > CONFIG_STM32_ETH_BUFSIZE DEBUGASSERT(priv->dev.d_len > 0 && priv->dev.d_buf != NULL);
#if CONFIG_NET_BUFSIZE > CONFIG_STM32_ETH_BUFSIZE
if (priv->dev.d_len > CONFIG_STM32_ETH_BUFSIZE) if (priv->dev.d_len > CONFIG_STM32_ETH_BUFSIZE)
{ {
/* Yes... how many buffers will be need to send the packet? */ /* Yes... how many buffers will be need to send the packet? */
@ -746,6 +899,8 @@ static int stm32_transmit(FAR struct stm32_ethmac_s *priv)
bufcount = (priv->dev.d_len + (CONFIG_STM32_ETH_BUFSIZE-1)) / CONFIG_STM32_ETH_BUFSIZE; bufcount = (priv->dev.d_len + (CONFIG_STM32_ETH_BUFSIZE-1)) / CONFIG_STM32_ETH_BUFSIZE;
lastsize = priv->dev.d_len - (bufcount - 1) * CONFIG_STM32_ETH_BUFSIZE; lastsize = priv->dev.d_len - (bufcount - 1) * CONFIG_STM32_ETH_BUFSIZE;
nllvdbg("bufcount: %d lastsize: %d\n", bufcount, lastsize);
/* Set the first segment bit in the first TX descriptor */ /* Set the first segment bit in the first TX descriptor */
txdesc->tdes0 |= ETH_TDES0_FS; txdesc->tdes0 |= ETH_TDES0_FS;
@ -842,24 +997,27 @@ static int stm32_transmit(FAR struct stm32_ethmac_s *priv)
priv->inflight++; priv->inflight++;
nllvdbg("txhead: %p txtail: %p inflight: %d\n",
priv->txhead, priv->txtail, priv->inflight);
/* Check if the TX Buffer unavailable flag is set */ /* Check if the TX Buffer unavailable flag is set */
if ((getreg32(STM32_ETH_DMASR) & ETH_DMAINT_TBUI) != 0) if ((stm32_getreg(STM32_ETH_DMASR) & ETH_DMAINT_TBUI) != 0)
{ {
/* Clear TX Buffer unavailable flag */ /* Clear TX Buffer unavailable flag */
putreg32(ETH_DMAINT_TBUI, STM32_ETH_DMASR); stm32_putreg(ETH_DMAINT_TBUI, STM32_ETH_DMASR);
/* Resume DMA transmission */ /* Resume DMA transmission */
putreg32(0, STM32_ETH_DMATPDR); stm32_putreg(0, STM32_ETH_DMATPDR);
} }
/* Enable TX interrupts */ /* Enable TX interrupts */
regval = getreg32(STM32_ETH_DMAIER); regval = stm32_getreg(STM32_ETH_DMAIER);
regval |= ETH_DMAINT_XMIT_ENABLE; regval |= ETH_DMAINT_XMIT_ENABLE;
putreg32(regval, STM32_ETH_DMAIER); stm32_putreg(regval, STM32_ETH_DMAIER);
/* Setup the TX timeout watchdog (perhaps restarting the timer) */ /* Setup the TX timeout watchdog (perhaps restarting the timer) */
@ -952,6 +1110,8 @@ static void stm32_freesegment(FAR struct stm32_ethmac_s *priv,
struct eth_rxdesc_s *rxdesc; struct eth_rxdesc_s *rxdesc;
int i; int i;
nllvdbg("rxfirst: %d segments: %d\n", rxfirst, segments);
/* Set OWN bit in RX descriptors. This gives the buffers back to DMA */ /* Set OWN bit in RX descriptors. This gives the buffers back to DMA */
rxdesc = rxfirst; rxdesc = rxfirst;
@ -968,15 +1128,15 @@ static void stm32_freesegment(FAR struct stm32_ethmac_s *priv,
/* Check if the RX Buffer unavailable flag is set */ /* Check if the RX Buffer unavailable flag is set */
if ((getreg32(STM32_ETH_DMASR) & ETH_DMAINT_RBUI) != 0) if ((stm32_getreg(STM32_ETH_DMASR) & ETH_DMAINT_RBUI) != 0)
{ {
/* Clear RBUS Ethernet DMA flag */ /* Clear RBUS Ethernet DMA flag */
putreg32(ETH_DMAINT_RBUI, STM32_ETH_DMASR); stm32_putreg(ETH_DMAINT_RBUI, STM32_ETH_DMASR);
/* Resume DMA reception */ /* Resume DMA reception */
putreg32(0, STM32_ETH_DMARPDR); stm32_putreg(0, STM32_ETH_DMARPDR);
} }
} }
@ -1008,6 +1168,9 @@ static int stm32_recvframe(FAR struct stm32_ethmac_s *priv)
uint8_t *buffer; uint8_t *buffer;
int i; int i;
nllvdbg("rxhead: %p rxcurr: %p segments: %d\n",
priv->rxhead, priv->rxcurr, priv->segments);
/* Check if there are free buffers. We cannot receive new frames in this /* Check if there are free buffers. We cannot receive new frames in this
* design unless there is at least one free buffer. * design unless there is at least one free buffer.
*/ */
@ -1048,6 +1211,9 @@ static int stm32_recvframe(FAR struct stm32_ethmac_s *priv)
{ {
priv->segments++; priv->segments++;
nllvdbg("rxhead: %p rxcurr: %p segments: %d\n",
priv->rxhead, priv->rxcurr, priv->segments);
/* Check if the there is only one segment in the frame */ /* Check if the there is only one segment in the frame */
if (priv->segments == 1) if (priv->segments == 1)
@ -1094,6 +1260,10 @@ static int stm32_recvframe(FAR struct stm32_ethmac_s *priv)
priv->rxhead = (struct eth_rxdesc_s*)rxdesc->rdes3; priv->rxhead = (struct eth_rxdesc_s*)rxdesc->rdes3;
stm32_freesegment(priv, rxcurr, priv->segments); stm32_freesegment(priv, rxcurr, priv->segments);
nllvdbg("rxhead: %p d_buf: %p d_len: %d\n",
priv->rxhead, dev->d_buf, dev->d_len);
return OK; return OK;
} }
else else
@ -1117,6 +1287,10 @@ static int stm32_recvframe(FAR struct stm32_ethmac_s *priv)
*/ */
priv->rxhead = rxdesc; priv->rxhead = rxdesc;
nllvdbg("rxhead: %p rxcurr: %p segments: %d\n",
priv->rxhead, priv->rxcurr, priv->segments);
return -EAGAIN; return -EAGAIN;
} }
@ -1164,6 +1338,10 @@ static void stm32_receive(FAR struct stm32_ethmac_s *priv)
else if (BUF->type == HTONS(UIP_ETHTYPE_IP)) else if (BUF->type == HTONS(UIP_ETHTYPE_IP))
#endif #endif
{ {
nllvdbg("IP frame\n");
/* Handle ARP on input then give the IP packet to uIP */
uip_arp_ipin(&priv->dev); uip_arp_ipin(&priv->dev);
uip_input(&priv->dev); uip_input(&priv->dev);
@ -1179,6 +1357,10 @@ static void stm32_receive(FAR struct stm32_ethmac_s *priv)
} }
else if (BUF->type == htons(UIP_ETHTYPE_ARP)) else if (BUF->type == htons(UIP_ETHTYPE_ARP))
{ {
nllvdbg("ARP frame\n");
/* Handle ARP packet */
uip_arp_arpin(&priv->dev); uip_arp_arpin(&priv->dev);
/* If the above function invocation resulted in data that should be /* If the above function invocation resulted in data that should be
@ -1232,6 +1414,9 @@ static void stm32_freeframe(FAR struct stm32_ethmac_s *priv)
struct eth_txdesc_s *txdesc; struct eth_txdesc_s *txdesc;
int i; int i;
nllvdbg("txhead: %p txtail: %p inflight: %d\n",
priv->txhead, priv->txtail, priv->inflight);
/* Scan for "in-flight" descriptors owned by the CPU */ /* Scan for "in-flight" descriptors owned by the CPU */
txdesc = priv->txtail; txdesc = priv->txtail;
@ -1286,6 +1471,9 @@ static void stm32_freeframe(FAR struct stm32_ethmac_s *priv)
*/ */
priv->txtail = txdesc; priv->txtail = txdesc;
nllvdbg("txhead: %p txtail: %p inflight: %d\n",
priv->txhead, priv->txtail, priv->inflight);
} }
} }
@ -1324,9 +1512,9 @@ static void stm32_txdone(FAR struct stm32_ethmac_s *priv)
/* And disable further TX interrupts. */ /* And disable further TX interrupts. */
regval = getreg32(STM32_ETH_DMAIER); regval = stm32_getreg(STM32_ETH_DMAIER);
regval &= ~ETH_DMAINT_XMIT_DISABLE; regval &= ~ETH_DMAINT_XMIT_DISABLE;
putreg32(regval, STM32_ETH_DMAIER); stm32_putreg(regval, STM32_ETH_DMAIER);
} }
/* Then poll uIP for new XMIT data */ /* Then poll uIP for new XMIT data */
@ -1358,13 +1546,13 @@ static int stm32_interrupt(int irq, FAR void *context)
/* Get the DMA interrupt status bits (no MAC interrupts are expected) */ /* Get the DMA interrupt status bits (no MAC interrupts are expected) */
dmasr = getreg32(STM32_ETH_DMASR); dmasr = stm32_getreg(STM32_ETH_DMASR);
/* Mask only enabled interrupts. This depends on the fact that the interrupt /* Mask only enabled interrupts. This depends on the fact that the interrupt
* related bits (0-16) correspond in these two registers. * related bits (0-16) correspond in these two registers.
*/ */
dmasr &= ~getreg32(STM32_ETH_DMAIER); dmasr &= ~stm32_getreg(STM32_ETH_DMAIER);
/* Check if there are pending "normal" interrupts */ /* Check if there are pending "normal" interrupts */
@ -1378,7 +1566,7 @@ static int stm32_interrupt(int irq, FAR void *context)
{ {
/* Clear the pending receive interrupt */ /* Clear the pending receive interrupt */
putreg32(ETH_DMAINT_RI, STM32_ETH_DMASR); stm32_putreg(ETH_DMAINT_RI, STM32_ETH_DMASR);
/* Handle the received package */ /* Handle the received package */
@ -1394,7 +1582,7 @@ static int stm32_interrupt(int irq, FAR void *context)
{ {
/* Clear the pending receive interrupt */ /* Clear the pending receive interrupt */
putreg32(ETH_DMAINT_TI, STM32_ETH_DMASR); stm32_putreg(ETH_DMAINT_TI, STM32_ETH_DMASR);
/* Check if there are pending transmissions */ /* Check if there are pending transmissions */
@ -1403,7 +1591,7 @@ static int stm32_interrupt(int irq, FAR void *context)
/* Clear the pending normal summary interrupt */ /* Clear the pending normal summary interrupt */
putreg32(ETH_DMAINT_NIS, STM32_ETH_DMASR); stm32_putreg(ETH_DMAINT_NIS, STM32_ETH_DMASR);
} }
/* Handle error interrupt only if CONFIG_DEBUG_NET is eanbled */ /* Handle error interrupt only if CONFIG_DEBUG_NET is eanbled */
@ -1420,11 +1608,11 @@ static int stm32_interrupt(int irq, FAR void *context)
/* Clear all pending abnormal events */ /* Clear all pending abnormal events */
putreg32(ETH_DMAINT_ABNORMAL, STM32_ETH_DMASR); stm32_putreg(ETH_DMAINT_ABNORMAL, STM32_ETH_DMASR);
/* Clear the pending normal summary interrupt */ /* Clear the pending normal summary interrupt */
putreg32(ETH_DMAINT_NIS, STM32_ETH_DMASR); stm32_putreg(ETH_DMAINT_NIS, STM32_ETH_DMASR);
} }
#endif #endif
return OK; return OK;
@ -1453,6 +1641,8 @@ static void stm32_txtimeout(int argc, uint32_t arg, ...)
{ {
FAR struct stm32_ethmac_s *priv = (FAR struct stm32_ethmac_s *)arg; FAR struct stm32_ethmac_s *priv = (FAR struct stm32_ethmac_s *)arg;
nlldbg("Timeout!\n");
/* Then reset the hardware. Just take the interface down, then back /* Then reset the hardware. Just take the interface down, then back
* up again. * up again.
*/ */
@ -1549,6 +1739,8 @@ static int stm32_ifup(struct uip_driver_s *dev)
priv->ifup = true; priv->ifup = true;
up_enable_irq(STM32_IRQ_ETH); up_enable_irq(STM32_IRQ_ETH);
stm32_checksetup();
return OK; return OK;
} }
@ -1573,6 +1765,8 @@ static int stm32_ifdown(struct uip_driver_s *dev)
FAR struct stm32_ethmac_s *priv = (FAR struct stm32_ethmac_s *)dev->d_private; FAR struct stm32_ethmac_s *priv = (FAR struct stm32_ethmac_s *)dev->d_private;
irqstate_t flags; irqstate_t flags;
ndbg("Taking the network down\n");
/* Disable the Ethernet interrupt */ /* Disable the Ethernet interrupt */
flags = irqsave(); flags = irqsave();
@ -1621,6 +1815,8 @@ static int stm32_txavail(struct uip_driver_s *dev)
FAR struct stm32_ethmac_s *priv = (FAR struct stm32_ethmac_s *)dev->d_private; FAR struct stm32_ethmac_s *priv = (FAR struct stm32_ethmac_s *)dev->d_private;
irqstate_t flags; irqstate_t flags;
nllvdbg("ifup: %d\n", priv->ifup);
/* Disable interrupts because this function may be called from interrupt /* Disable interrupts because this function may be called from interrupt
* level processing. * level processing.
*/ */
@ -1672,6 +1868,10 @@ static int stm32_addmac(struct uip_driver_s *dev, FAR const uint8_t *mac)
{ {
FAR struct stm32_ethmac_s *priv = (FAR struct stm32_ethmac_s *)dev->d_private; FAR struct stm32_ethmac_s *priv = (FAR struct stm32_ethmac_s *)dev->d_private;
nllvdbg("MAC: %02x:%02x:%02x:%02x:%02x:%02x\n",
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
/* Add the MAC address to the hardware multicast routing table */
/* Add the MAC address to the hardware multicast routing table */ /* Add the MAC address to the hardware multicast routing table */
#error "Missing logic" #error "Missing logic"
@ -1702,6 +1902,9 @@ static int stm32_rmmac(struct uip_driver_s *dev, FAR const uint8_t *mac)
{ {
FAR struct stm32_ethmac_s *priv = (FAR struct stm32_ethmac_s *)dev->d_private; FAR struct stm32_ethmac_s *priv = (FAR struct stm32_ethmac_s *)dev->d_private;
nllvdbg("MAC: %02x:%02x:%02x:%02x:%02x:%02x\n",
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
/* Add the MAC address to the hardware multicast routing table */ /* Add the MAC address to the hardware multicast routing table */
#error "Missing logic" #error "Missing logic"
@ -1788,7 +1991,7 @@ static void stm32_txdescinit(FAR struct stm32_ethmac_s *priv)
/* Set Transmit Desciptor List Address Register */ /* Set Transmit Desciptor List Address Register */
putreg32((uint32_t)priv->txtable, STM32_ETH_DMATDLAR); stm32_putreg((uint32_t)priv->txtable, STM32_ETH_DMATDLAR);
} }
/**************************************************************************** /****************************************************************************
@ -1867,7 +2070,7 @@ static void stm32_rxdescinit(FAR struct stm32_ethmac_s *priv)
/* Set Receive Descriptor List Address Register */ /* Set Receive Descriptor List Address Register */
putreg32((uint32_t)priv->rxtable, STM32_ETH_DMARDLAR); stm32_putreg((uint32_t)priv->rxtable, STM32_ETH_DMARDLAR);
} }
/**************************************************************************** /****************************************************************************
@ -1895,7 +2098,7 @@ static int stm32_phyread(uint16_t phydevaddr, uint16_t phyregaddr, uint16_t *val
/* Configure the MACMIIAR register, preserving CSR Clock Range CR[2:0] bits */ /* Configure the MACMIIAR register, preserving CSR Clock Range CR[2:0] bits */
regval = getreg32(STM32_ETH_MACMIIAR); regval = stm32_getreg(STM32_ETH_MACMIIAR);
regval &= ETH_MACMIIAR_CR_MASK; regval &= ETH_MACMIIAR_CR_MASK;
/* Set the PHY device address, PHY register address, and set the buy bit. /* Set the PHY device address, PHY register address, and set the buy bit.
@ -1906,15 +2109,15 @@ static int stm32_phyread(uint16_t phydevaddr, uint16_t phyregaddr, uint16_t *val
regval |= (((uint32_t)phyregaddr << ETH_MACMIIAR_MR_SHIFT) & ETH_MACMIIAR_MR_MASK); regval |= (((uint32_t)phyregaddr << ETH_MACMIIAR_MR_SHIFT) & ETH_MACMIIAR_MR_MASK);
regval |= ETH_MACMIIAR_MB; regval |= ETH_MACMIIAR_MB;
putreg32(regval, STM32_ETH_MACMIIAR); stm32_putreg(regval, STM32_ETH_MACMIIAR);
/* Wait for the transfer to complete */ /* Wait for the transfer to complete */
for (timeout = 0; timeout < PHY_READ_TIMEOUT; timeout++) for (timeout = 0; timeout < PHY_READ_TIMEOUT; timeout++)
{ {
if ((getreg32(STM32_ETH_MACMIIAR) && ETH_MACMIIAR_MB) == 0) if ((stm32_getreg(STM32_ETH_MACMIIAR) & ETH_MACMIIAR_MB) == 0)
{ {
*value = (uint16_t)getreg32(STM32_ETH_MACMIIDR); *value = (uint16_t)stm32_getreg(STM32_ETH_MACMIIDR);
return OK; return OK;
} }
} }
@ -1950,7 +2153,7 @@ static int stm32_phywrite(uint16_t phydevaddr, uint16_t phyregaddr, uint16_t val
/* Configure the MACMIIAR register, preserving CSR Clock Range CR[2:0] bits */ /* Configure the MACMIIAR register, preserving CSR Clock Range CR[2:0] bits */
regval = getreg32(STM32_ETH_MACMIIAR); regval = stm32_getreg(STM32_ETH_MACMIIAR);
regval &= ETH_MACMIIAR_CR_MASK; regval &= ETH_MACMIIAR_CR_MASK;
/* Set the PHY device address, PHY register address, and set the busy bit. /* Set the PHY device address, PHY register address, and set the busy bit.
@ -1965,14 +2168,14 @@ static int stm32_phywrite(uint16_t phydevaddr, uint16_t phyregaddr, uint16_t val
* register value. * register value.
*/ */
putreg32(value, STM32_ETH_MACMIIDR); stm32_putreg(value, STM32_ETH_MACMIIDR);
putreg32(regval, STM32_ETH_MACMIIAR); stm32_putreg(regval, STM32_ETH_MACMIIAR);
/* Wait for the transfer to complete */ /* Wait for the transfer to complete */
for (timeout = 0; timeout < PHY_WRITE_TIMEOUT; timeout++) for (timeout = 0; timeout < PHY_WRITE_TIMEOUT; timeout++)
{ {
if ((getreg32(STM32_ETH_MACMIIAR) && ETH_MACMIIAR_MB) == 0) if ((stm32_getreg(STM32_ETH_MACMIIAR) & ETH_MACMIIAR_MB) == 0)
{ {
return OK; return OK;
} }
@ -2014,16 +2217,17 @@ static int stm32_phyinit(FAR struct stm32_ethmac_s *priv)
/* Setup up PHY clocking by setting the SR field in the MACMIIAR register */ /* Setup up PHY clocking by setting the SR field in the MACMIIAR register */
regval = getreg32(STM32_ETH_MACMIIAR); regval = stm32_getreg(STM32_ETH_MACMIIAR);
regval &= ~ETH_MACMIIAR_CR_MASK; regval &= ~ETH_MACMIIAR_CR_MASK;
regval |= ETH_MACMIIAR_CR; regval |= ETH_MACMIIAR_CR;
putreg32(regval, STM32_ETH_MACMIIAR); stm32_putreg(regval, STM32_ETH_MACMIIAR);
/* Put the PHY in reset mode */ /* Put the PHY in reset mode */
ret = stm32_phywrite(CONFIG_STM32_PHYADDR, MII_MCR, MII_MCR_RESET); ret = stm32_phywrite(CONFIG_STM32_PHYADDR, MII_MCR, MII_MCR_RESET);
if (ret < 0) if (ret < 0)
{ {
ndbg("Failed to reset the PHY: %d\n", ret);
return ret; return ret;
} }
up_mdelay(PHY_RESET_DELAY); up_mdelay(PHY_RESET_DELAY);
@ -2038,6 +2242,7 @@ static int stm32_phyinit(FAR struct stm32_ethmac_s *priv)
ret = stm32_phyread(CONFIG_STM32_PHYADDR, MII_MSR, &phyval); ret = stm32_phyread(CONFIG_STM32_PHYADDR, MII_MSR, &phyval);
if (ret < 0) if (ret < 0)
{ {
ndbg("Failed to read the PHY MSR: %d\n", ret);
return ret; return ret;
} }
else if ((phyval & MII_MSR_LINKSTATUS) != 0) else if ((phyval & MII_MSR_LINKSTATUS) != 0)
@ -2057,6 +2262,7 @@ static int stm32_phyinit(FAR struct stm32_ethmac_s *priv)
ret = stm32_phywrite(CONFIG_STM32_PHYADDR, MII_MCR, MII_MCR_ANENABLE); ret = stm32_phywrite(CONFIG_STM32_PHYADDR, MII_MCR, MII_MCR_ANENABLE);
if (ret < 0) if (ret < 0)
{ {
ndbg("Failed to enable auto-negotiation: %d\n", ret);
return ret; return ret;
} }
@ -2067,6 +2273,7 @@ static int stm32_phyinit(FAR struct stm32_ethmac_s *priv)
ret = stm32_phyread(CONFIG_STM32_PHYADDR, MII_MSR, &phyval); ret = stm32_phyread(CONFIG_STM32_PHYADDR, MII_MSR, &phyval);
if (ret < 0) if (ret < 0)
{ {
ndbg("Failed to read the PHY MSR: %d\n", ret);
return ret; return ret;
} }
else if ((phyval & MII_MSR_ANEGCOMPLETE) != 0) else if ((phyval & MII_MSR_ANEGCOMPLETE) != 0)
@ -2115,6 +2322,7 @@ static int stm32_phyinit(FAR struct stm32_ethmac_s *priv)
ret = stm32_phywrite(CONFIG_STM32_PHYADDR, MII_MCR, phyval); ret = stm32_phywrite(CONFIG_STM32_PHYADDR, MII_MCR, phyval);
if (ret < 0) if (ret < 0)
{ {
ndbg("Failed to write the PHY MCR: %d\n", ret);
return ret; return ret;
} }
up_mdelay(PHY_CONFIG_DELAY); up_mdelay(PHY_CONFIG_DELAY);
@ -2128,6 +2336,11 @@ static int stm32_phyinit(FAR struct stm32_ethmac_s *priv)
priv->mbps100 = 1; priv->mbps100 = 1;
#endif #endif
#endif #endif
ndbg("Duplex: %s Speed: %d MBps\n",
priv->fduplex ? "FULL" : "HALF",
priv->mbps100 ? 100 : 10);
return OK; return OK;
} }
@ -2267,27 +2480,27 @@ static void stm32_ethreset(FAR struct stm32_ethmac_s *priv)
/* Reset the Ethernet on the AHB1 bus */ /* Reset the Ethernet on the AHB1 bus */
regval = getreg32(STM32_RCC_AHB1RSTR); regval = stm32_getreg(STM32_RCC_AHB1RSTR);
regval |= RCC_AHB1RSTR_ETHMACRST; regval |= RCC_AHB1RSTR_ETHMACRST;
putreg32(regval, STM32_RCC_AHB1RSTR); stm32_putreg(regval, STM32_RCC_AHB1RSTR);
regval &= ~RCC_AHB1RSTR_ETHMACRST; regval &= ~RCC_AHB1RSTR_ETHMACRST;
putreg32(regval, STM32_RCC_AHB1RSTR); stm32_putreg(regval, STM32_RCC_AHB1RSTR);
/* Perform a software reset by setting the SR bit in the DMABMR register. /* Perform a software reset by setting the SR bit in the DMABMR register.
* This Resets all MAC subsystem internal registers and logic. After this * This Resets all MAC subsystem internal registers and logic. After this
* reset all the registers holds their reset values. * reset all the registers holds their reset values.
*/ */
regval = getreg32(STM32_ETH_DMABMR); regval = stm32_getreg(STM32_ETH_DMABMR);
regval |= ETH_DMABMR_SR; regval |= ETH_DMABMR_SR;
putreg32(regval, STM32_ETH_DMABMR); stm32_putreg(regval, STM32_ETH_DMABMR);
/* Wait for software reset to complete. The SR bit is cleared automatically /* Wait for software reset to complete. The SR bit is cleared automatically
* after the reset operation has completed in all of the core clock domains. * after the reset operation has completed in all of the core clock domains.
*/ */
while ((getreg32(STM32_ETH_DMABMR) & ETH_DMABMR_SR) != 0); while ((stm32_getreg(STM32_ETH_DMABMR) & ETH_DMABMR_SR) != 0);
} }
/**************************************************************************** /****************************************************************************
@ -2312,7 +2525,7 @@ static int stm32_macconfig(FAR struct stm32_ethmac_s *priv)
/* Set up the MACCR register */ /* Set up the MACCR register */
regval = getreg32(STM32_ETH_MACCR); regval = stm32_getreg(STM32_ETH_MACCR);
regval &= ~MACCR_CLEAR_BITS; regval &= ~MACCR_CLEAR_BITS;
regval |= MACCR_SET_BITS; regval |= MACCR_SET_BITS;
@ -2330,45 +2543,45 @@ static int stm32_macconfig(FAR struct stm32_ethmac_s *priv)
regval |= ETH_MACCR_FES; regval |= ETH_MACCR_FES;
} }
putreg32(regval, STM32_ETH_MACCR); stm32_putreg(regval, STM32_ETH_MACCR);
/* Set up the MACFFR register */ /* Set up the MACFFR register */
regval = getreg32(STM32_ETH_MACFFR); regval = stm32_getreg(STM32_ETH_MACFFR);
regval &= ~MACFFR_CLEAR_BITS; regval &= ~MACFFR_CLEAR_BITS;
regval |= MACFFR_SET_BITS; regval |= MACFFR_SET_BITS;
putreg32(regval, STM32_ETH_MACFFR); stm32_putreg(regval, STM32_ETH_MACFFR);
/* Set up the MACHTHR and MACHTLR registers */ /* Set up the MACHTHR and MACHTLR registers */
putreg32(0, STM32_ETH_MACHTHR); stm32_putreg(0, STM32_ETH_MACHTHR);
putreg32(0, STM32_ETH_MACHTLR); stm32_putreg(0, STM32_ETH_MACHTLR);
/* Setup up the MACFCR register */ /* Setup up the MACFCR register */
regval = getreg32(STM32_ETH_MACFCR); regval = stm32_getreg(STM32_ETH_MACFCR);
regval &= ~MACFCR_CLEAR_MASK; regval &= ~MACFCR_CLEAR_MASK;
regval |= MACFCR_SET_MASK; regval |= MACFCR_SET_MASK;
putreg32(regval, STM32_ETH_MACFCR); stm32_putreg(regval, STM32_ETH_MACFCR);
/* Setup up the MACVLANTR register */ /* Setup up the MACVLANTR register */
putreg32(0, STM32_ETH_MACVLANTR); stm32_putreg(0, STM32_ETH_MACVLANTR);
/* DMA Configuration */ /* DMA Configuration */
/* Set up the DMAOMR register */ /* Set up the DMAOMR register */
regval = getreg32(STM32_ETH_DMAOMR); regval = stm32_getreg(STM32_ETH_DMAOMR);
regval &= ~DMAOMR_CLEAR_MASK; regval &= ~DMAOMR_CLEAR_MASK;
regval |= DMAOMR_SET_MASK; regval |= DMAOMR_SET_MASK;
putreg32(regval, STM32_ETH_DMAOMR); stm32_putreg(regval, STM32_ETH_DMAOMR);
/* Set up the DMABMR register */ /* Set up the DMABMR register */
regval = getreg32(STM32_ETH_DMABMR); regval = stm32_getreg(STM32_ETH_DMABMR);
regval &= ~DMABMR_CLEAR_MASK; regval &= ~DMABMR_CLEAR_MASK;
regval |= DMABMR_SET_MASK; regval |= DMABMR_SET_MASK;
putreg32(regval, STM32_ETH_DMABMR); stm32_putreg(regval, STM32_ETH_DMABMR);
return OK; return OK;
} }
@ -2391,21 +2604,28 @@ static int stm32_macconfig(FAR struct stm32_ethmac_s *priv)
static void stm32_macaddress(FAR struct stm32_ethmac_s *priv) static void stm32_macaddress(FAR struct stm32_ethmac_s *priv)
{ {
FAR struct uip_driver_s *dev = &priv->dev;
uint32_t regval; uint32_t regval;
nllvdbg("%s MAC: %02x:%02x:%02x:%02x:%02x:%02x\n",
dev->d_ifname,
dev->d_mac.ether_addr_octet[0], dev->d_mac.ether_addr_octet[1],
dev->d_mac.ether_addr_octet[2], dev->d_mac.ether_addr_octet[3],
dev->d_mac.ether_addr_octet[4], dev->d_mac.ether_addr_octet[5]);
/* Set the MAC address high register */ /* Set the MAC address high register */
regval = ((uint32_t)priv->dev.d_mac.ether_addr_octet[5] << 8) | regval = ((uint32_t)dev->d_mac.ether_addr_octet[5] << 8) |
(uint32_t)priv->dev.d_mac.ether_addr_octet[4]; (uint32_t)dev->d_mac.ether_addr_octet[4];
putreg32(regval, STM32_ETH_MACA0HR); stm32_putreg(regval, STM32_ETH_MACA0HR);
/* Set the MAC address low register */ /* Set the MAC address low register */
regval = ((uint32_t)priv->dev.d_mac.ether_addr_octet[3] << 24) | regval = ((uint32_t)dev->d_mac.ether_addr_octet[3] << 24) |
((uint32_t)priv->dev.d_mac.ether_addr_octet[2] << 16) | ((uint32_t)dev->d_mac.ether_addr_octet[2] << 16) |
((uint32_t)priv->dev.d_mac.ether_addr_octet[1] << 8) | ((uint32_t)dev->d_mac.ether_addr_octet[1] << 8) |
(uint32_t)priv->dev.d_mac.ether_addr_octet[0]; (uint32_t)dev->d_mac.ether_addr_octet[0];
putreg32(regval, STM32_ETH_MACA0LR); stm32_putreg(regval, STM32_ETH_MACA0LR);
} }
/**************************************************************************** /****************************************************************************
@ -2434,35 +2654,35 @@ static int stm32_macenable(FAR struct stm32_ethmac_s *priv)
/* Enable transmit state machine of the MAC for transmission on the MII */ /* Enable transmit state machine of the MAC for transmission on the MII */
regval = getreg32(STM32_ETH_MACCR); regval = stm32_getreg(STM32_ETH_MACCR);
regval |= ETH_MACCR_TE; regval |= ETH_MACCR_TE;
putreg32(regval, STM32_ETH_MACCR); stm32_putreg(regval, STM32_ETH_MACCR);
/* Flush Transmit FIFO */ /* Flush Transmit FIFO */
regval = getreg32(STM32_ETH_DMAOMR); regval = stm32_getreg(STM32_ETH_DMAOMR);
regval |= ETH_DMAOMR_FTF; regval |= ETH_DMAOMR_FTF;
putreg32(regval, STM32_ETH_DMAOMR); stm32_putreg(regval, STM32_ETH_DMAOMR);
/* Enable receive state machine of the MAC for reception from the MII */ /* Enable receive state machine of the MAC for reception from the MII */
/* Enables or disables the MAC reception. */ /* Enables or disables the MAC reception. */
regval = getreg32(STM32_ETH_MACCR); regval = stm32_getreg(STM32_ETH_MACCR);
regval |= ETH_MACCR_RE; regval |= ETH_MACCR_RE;
putreg32(regval, STM32_ETH_MACCR); stm32_putreg(regval, STM32_ETH_MACCR);
/* Start DMA transmission */ /* Start DMA transmission */
regval = getreg32(STM32_ETH_DMAOMR); regval = stm32_getreg(STM32_ETH_DMAOMR);
regval |= ETH_DMAOMR_ST; regval |= ETH_DMAOMR_ST;
putreg32(regval, STM32_ETH_DMAOMR); stm32_putreg(regval, STM32_ETH_DMAOMR);
/* Start DMA reception */ /* Start DMA reception */
regval = getreg32(STM32_ETH_DMAOMR); regval = stm32_getreg(STM32_ETH_DMAOMR);
regval |= ETH_DMAOMR_SR; regval |= ETH_DMAOMR_SR;
putreg32(regval, STM32_ETH_DMAOMR); stm32_putreg(regval, STM32_ETH_DMAOMR);
/* Enable Ethernet DMA interrupts. /* Enable Ethernet DMA interrupts.
* *
@ -2475,7 +2695,7 @@ static int stm32_macenable(FAR struct stm32_ethmac_s *priv)
* neither of which are used by this driver. * neither of which are used by this driver.
*/ */
putreg32(ETH_MACIMR_ALLINTS, STM32_ETH_MACIMR); stm32_putreg(ETH_MACIMR_ALLINTS, STM32_ETH_MACIMR);
/* Ethernet DMA supports two classes of interrupts: Normal interrupt /* Ethernet DMA supports two classes of interrupts: Normal interrupt
* summary (NIS) and Abnormal interrupt summary (AIS) with a variety * summary (NIS) and Abnormal interrupt summary (AIS) with a variety
@ -2484,7 +2704,7 @@ static int stm32_macenable(FAR struct stm32_ethmac_s *priv)
* events will only be enabled when a transmit interrupt is expected. * events will only be enabled when a transmit interrupt is expected.
*/ */
putreg32((ETH_DMAINT_RECV_ENABLE | ETH_DMAINT_ERROR_ENABLE), STM32_ETH_DMAIER); stm32_putreg((ETH_DMAINT_RECV_ENABLE | ETH_DMAINT_ERROR_ENABLE), STM32_ETH_DMAIER);
return OK; return OK;
} }
@ -2514,10 +2734,12 @@ static int stm32_ethconfig(FAR struct stm32_ethmac_s *priv)
/* Reset the Ethernet block */ /* Reset the Ethernet block */
nllvdbg("Reset the Ethernet block\n");
stm32_ethreset(priv); stm32_ethreset(priv);
/* Initialize the PHY */ /* Initialize the PHY */
nllvdbg("Initialize the PHY\n");
ret = stm32_phyinit(priv); ret = stm32_phyinit(priv);
if (ret < 0) if (ret < 0)
{ {
@ -2526,6 +2748,7 @@ static int stm32_ethconfig(FAR struct stm32_ethmac_s *priv)
/* Initialize the MAC and DMA */ /* Initialize the MAC and DMA */
nllvdbg("Initialize the MAC and DMA\n");
ret = stm32_macconfig(priv); ret = stm32_macconfig(priv);
if (ret < 0) if (ret < 0)
{ {
@ -2546,6 +2769,7 @@ static int stm32_ethconfig(FAR struct stm32_ethmac_s *priv)
/* Enable normal MAC operation */ /* Enable normal MAC operation */
nllvdbg("Enable normal operation\n");
return stm32_macenable(priv); return stm32_macenable(priv);
} }
@ -2581,6 +2805,8 @@ int stm32_ethinitialize(int intf)
{ {
struct stm32_ethmac_s *priv; struct stm32_ethmac_s *priv;
nvdbg("intf: %d\n", intf);
/* Get the interface structure associated with this interface number. */ /* Get the interface structure associated with this interface number. */
DEBUGASSERT(intf < STM32_NETHERNET); DEBUGASSERT(intf < STM32_NETHERNET);

View File

@ -13,6 +13,7 @@ Contents
- NuttX buildroot Toolchain - NuttX buildroot Toolchain
- STM3240G-EVAL-specific Configuration Options - STM3240G-EVAL-specific Configuration Options
- LEDs - LEDs
- Ethernet
- Configurations - Configurations
Development Environment Development Environment
@ -161,6 +162,19 @@ NuttX buildroot Toolchain
detailed PLUS some special instructions that you will need to follow if you are detailed PLUS some special instructions that you will need to follow if you are
building a Cortex-M3 toolchain for Cygwin under Windows. building a Cortex-M3 toolchain for Cygwin under Windows.
Ethernet
========
The Ethernet driver is configured to use the MII interface:
Board Jumper Settings:
Jumper Description
JP8 To enable MII, JP8 should not be fitted.
JP6 2-3: Enable MII interface mode
JP5 2-3: Provide 25 MHz clock for MII or 50 MHz clock for RMII by MCO at PA8
SB1 Not used with MII
LEDs LEDs
==== ====

View File

@ -1061,7 +1061,7 @@ CONFIG_NSH_DISABLESCRIPT=n
CONFIG_NSH_DISABLEBG=n CONFIG_NSH_DISABLEBG=n
CONFIG_NSH_ROMFSETC=n CONFIG_NSH_ROMFSETC=n
CONFIG_NSH_CONSOLE=y CONFIG_NSH_CONSOLE=y
CONFIG_NSH_TELNET=n CONFIG_NSH_TELNET=y
CONFIG_NSH_ARCHINIT=n CONFIG_NSH_ARCHINIT=n
CONFIG_NSH_IOBUFFER_SIZE=512 CONFIG_NSH_IOBUFFER_SIZE=512
CONFIG_NSH_DHCPC=n CONFIG_NSH_DHCPC=n