diff --git a/os/hal/platforms/STM32/mac_lld.c b/os/hal/platforms/STM32/mac_lld.c index 0af994f99..cfd8282fc 100644 --- a/os/hal/platforms/STM32/mac_lld.c +++ b/os/hal/platforms/STM32/mac_lld.c @@ -26,6 +26,8 @@ * @{ */ +#include + #include "ch.h" #include "hal.h" #include "mii.h" @@ -258,7 +260,7 @@ void mac_lld_init(void) { #endif /* PHY in power down mode until the driver will be started.*/ -/* mii_write(ÐD1, MII_BMCR, BMCR_PDOWN);*/ + mii_write(ÐD1, MII_BMCR, mii_read(ÐD1, MII_BMCR) | BMCR_PDOWN); /* MAC clocks stopped again.*/ rccDisableETH(FALSE); @@ -274,7 +276,6 @@ void mac_lld_init(void) { void mac_lld_start(MACDriver *macp) { unsigned i; - /* Resets the state of all descriptors.*/ for (i = 0; i < STM32_MAC_RECEIVE_BUFFERS; i++) rd[i].rdes0 = STM32_RDES0_OWN; @@ -292,6 +293,9 @@ void mac_lld_start(MACDriver *macp) { /* ISR vector enabled.*/ nvicEnableVector(ETH_IRQn, CORTEX_PRIORITY_MASK(STM32_ETH1_IRQ_PRIORITY)); + /* PHY in power up mode.*/ + mii_write(macp, MII_BMCR, mii_read(macp, MII_BMCR) & ~BMCR_PDOWN); + /* MAC configuration: ETH_MACFFR_SAF - Source address filter. Broadcast frames are not filtered.*/ @@ -343,19 +347,22 @@ void mac_lld_start(MACDriver *macp) { */ void mac_lld_stop(MACDriver *macp) { - (void)macp; + if (macp->state != MAC_STOP) { + /* PHY in power down mode until the driver will be restarted.*/ + mii_write(macp, MII_BMCR, mii_read(macp, MII_BMCR) | BMCR_PDOWN); - /* MAC and DMA stopped.*/ - ETH->MACCR = 0; - ETH->DMAOMR = 0; - ETH->DMAIER = 0; - ETH->DMASR = ETH->DMASR; + /* MAC and DMA stopped.*/ + ETH->MACCR = 0; + ETH->DMAOMR = 0; + ETH->DMAIER = 0; + ETH->DMASR = ETH->DMASR; - /* MAC clocks stopped.*/ - rccDisableETH(FALSE); + /* MAC clocks stopped.*/ + rccDisableETH(FALSE); - /* ISR vector disabled.*/ - nvicDisableVector(ETH_IRQn); + /* ISR vector disabled.*/ + nvicDisableVector(ETH_IRQn); + } } /** @@ -373,9 +380,35 @@ void mac_lld_stop(MACDriver *macp) { */ msg_t max_lld_get_transmit_descriptor(MACDriver *macp, MACTransmitDescriptor *tdp) { + stm32_eth_tx_descriptor_t *tdes; - (void)macp; - (void)tdp; + if (!macp->link_up) + return RDY_TIMEOUT; + + chSysLock(); + + /* Get Current TX descriptor.*/ + tdes = macp->txptr; + + /* Ensure that descriptor isn't owned by the Ethernet DMA or locked by + another thread.*/ + if (tdes->tdes0 & (STM32_TDES0_OWN | STM32_TDES0_LOCKED)) { + chSysUnlock(); + return RDY_TIMEOUT; + } + + /* Marks the current descriptor as locked using a reserved bit.*/ + tdes->tdes0 |= STM32_TDES0_LOCKED; + + /* Next TX descriptor to use.*/ + macp->txptr = (stm32_eth_tx_descriptor_t *)tdes->tdes3; + + chSysUnlock(); + + /* Set the buffer size and configuration.*/ + tdp->offset = 0; + tdp->size = STM32_MAC_BUFFERS_SIZE; + tdp->physdesc = tdes; return RDY_OK; } @@ -398,11 +431,18 @@ size_t mac_lld_write_transmit_descriptor(MACTransmitDescriptor *tdp, uint8_t *buf, size_t size) { - (void)tdp; - (void)buf; - (void)size; + chDbgAssert(!(tdp->physdesc->tdes0 & STM32_TDES0_OWN), + "mac_lld_release_receive_descriptor(), #1", + "attempt to write descriptor already owned by DMA"); - return 0; + if (size > tdp->size - tdp->offset) + size = tdp->size - tdp->offset; + + if (size > 0) { + memcpy((uint8_t *)(tdp->physdesc->tdes2) + tdp->offset, buf, size); + tdp->offset += size; + } + return size; } /** @@ -415,7 +455,24 @@ size_t mac_lld_write_transmit_descriptor(MACTransmitDescriptor *tdp, */ void mac_lld_release_transmit_descriptor(MACTransmitDescriptor *tdp) { - (void)tdp; + chDbgAssert(!(tdp->physdesc->tdes0 & STM32_TDES0_OWN), + "mac_lld_release_transmit_descriptor(), #1", + "attempt to release descriptor already owned by DMA"); + + chSysLock(); + + /* Unlocks the descriptor and returns it to the DMA engine.*/ + tdp->physdesc->tdes1 = tdp->offset; + tdp->physdesc->tdes0 = STM32_TDES0_IC | STM32_TDES0_LS | STM32_TDES0_FS | + STM32_TDES0_OWN; + + /* If the DMA engine is stalled then a restart request is issued.*/ + if ((ETH->DMASR & 0x700000) == 0x600000) { + ETH->DMASR = ETH_DMASR_TBUS; + ETH->DMATPDR = ETH_DMASR_TBUS; /* Any value is OK.*/ + } + + chSysUnlock(); } /** diff --git a/os/hal/platforms/STM32/mac_lld.h b/os/hal/platforms/STM32/mac_lld.h index aa07535b0..077ddd2ec 100644 --- a/os/hal/platforms/STM32/mac_lld.h +++ b/os/hal/platforms/STM32/mac_lld.h @@ -82,6 +82,7 @@ #define STM32_TDES0_DC 0x08000000 #define STM32_TDES0_DP 0x04000000 #define STM32_TDES0_TTSE 0x02000000 +#define STM32_TDES0_LOCKED 0x01000000 /* NOTE: Pseudo flag. */ #define STM32_TDES0_CIC_MASK 0x00C00000 #define STM32_TDES0_TER 0x00200000 #define STM32_TDES0_TCH 0x00100000 @@ -136,7 +137,7 @@ * @brief Maximum supported frame size. */ #if !defined(MAC_BUFFERS_SIZE) || defined(__DOXYGEN__) -#define STM32_MAC_BUFFERS_SIZE 1520 +#define STM32_MAC_BUFFERS_SIZE 1518 #endif /** @@ -238,12 +239,16 @@ typedef struct { /** * @brief Current write offset. */ - size_t offset; + size_t offset; /** * @brief Available space size. */ - size_t size; + size_t size; /* End of the mandatory fields.*/ + /** + * @brief Pointer to the physical descriptor. + */ + stm32_eth_tx_descriptor_t *physdesc; } MACTransmitDescriptor; /** @@ -259,6 +264,10 @@ typedef struct { */ size_t size; /* End of the mandatory fields.*/ + /** + * @brief Pointer to the physical descriptor. + */ + stm32_eth_rx_descriptor_t *physdesc; } MACReceiveDescriptor; /*===========================================================================*/