From fb4739b12b905317a2a9d680f5e0b79b2c780374 Mon Sep 17 00:00:00 2001 From: gdisirio Date: Sat, 5 Jul 2014 16:09:29 +0000 Subject: lwIP code by Eddie, not fully "RT-free" in the HAL LLD. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@7009 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/hal.mk | 1 + os/hal/include/hal.h | 3 +- os/hal/include/mac.h | 214 +++++++++++++++++++++++++++++++ os/hal/include/mii.h | 162 +++++++++++++++++++++++ os/hal/ports/STM32/LLD/mac_lld.c | 65 +++++----- os/hal/ports/STM32/LLD/mac_lld.h | 6 +- os/hal/src/mac.c | 268 +++++++++++++++++++++++++++++++++++++++ 7 files changed, 681 insertions(+), 38 deletions(-) create mode 100644 os/hal/include/mac.h create mode 100644 os/hal/include/mii.h create mode 100644 os/hal/src/mac.c (limited to 'os/hal') diff --git a/os/hal/hal.mk b/os/hal/hal.mk index 2892a7652..c0c239228 100644 --- a/os/hal/hal.mk +++ b/os/hal/hal.mk @@ -11,6 +11,7 @@ HALSRC = ${CHIBIOS}/os/hal/src/hal.c \ ${CHIBIOS}/os/hal/src/i2c.c \ ${CHIBIOS}/os/hal/src/i2s.c \ ${CHIBIOS}/os/hal/src/icu.c \ + ${CHIBIOS}/os/hal/src/mac.c \ ${CHIBIOS}/os/hal/src/mmc_spi.c \ ${CHIBIOS}/os/hal/src/pal.c \ ${CHIBIOS}/os/hal/src/pwm.c \ diff --git a/os/hal/include/hal.h b/os/hal/include/hal.h index 31ed18bc0..597bf44dc 100644 --- a/os/hal/include/hal.h +++ b/os/hal/include/hal.h @@ -54,7 +54,8 @@ #include "i2c.h" #include "i2s.h" #include "icu.h" -//#include "mac.h" +#include "mac.h" +#include "mii.h" #include "pwm.h" #include "rtc.h" #include "serial.h" diff --git a/os/hal/include/mac.h b/os/hal/include/mac.h new file mode 100644 index 000000000..8b882054a --- /dev/null +++ b/os/hal/include/mac.h @@ -0,0 +1,214 @@ +/* + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010, + 2011,2012,2013 Giovanni Di Sirio. + + This file is part of ChibiOS/RT. + + ChibiOS/RT is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/RT is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file mac.h + * @brief MAC Driver macros and structures. + * @addtogroup MAC + * @{ + */ + +#ifndef _MAC_H_ +#define _MAC_H_ + +#if HAL_USE_MAC || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name MAC configuration options + * @{ + */ +/** + * @brief Enables an event sources for incoming packets. + */ +#if !defined(MAC_USE_ZERO_COPY) || defined(__DOXYGEN__) +#define MAC_USE_ZERO_COPY FALSE +#endif + +/** + * @brief Enables an event sources for incoming packets. + */ +#if !defined(MAC_USE_EVENTS) || defined(__DOXYGEN__) +#define MAC_USE_EVENTS TRUE +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +#if !CH_CFG_USE_SEMAPHORES || !CH_CFG_USE_EVENTS +#error "the MAC driver requires CH_CFG_USE_SEMAPHORES" +#endif + +#if MAC_USE_EVENTS && !CH_CFG_USE_EVENTS +#error "the MAC driver requires CH_CFG_USE_EVENTS" +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief Driver state machine possible states. + */ +typedef enum { + MAC_UNINIT = 0, /**< Not initialized. */ + MAC_STOP = 1, /**< Stopped. */ + MAC_ACTIVE = 2 /**< Active. */ +} macstate_t; + +/** + * @brief Type of a structure representing a MAC driver. + */ +typedef struct MACDriver MACDriver; + +#include "mac_lld.h" + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/** + * @name Macro Functions + * @{ + */ +/** + * @brief Returns the received frames event source. + * + * @param[in] macp pointer to the @p MACDriver object + * @return The pointer to the @p EventSource structure. + * + * @api + */ +#if MAC_USE_EVENTS || defined(__DOXYGEN__) +#define macGetReceiveEventSource(macp) (&(macp)->rdevent) +#endif + +/** + * @brief Writes to a transmit descriptor's stream. + * + * @param[in] tdp pointer to a @p MACTransmitDescriptor structure + * @param[in] buf pointer to the buffer containing the data to be written + * @param[in] size number of bytes to be written + * @return The number of bytes written into the descriptor's + * stream, this value can be less than the amount + * specified in the parameter @p size if the maximum frame + * size is reached. + * + * @api + */ +#define macWriteTransmitDescriptor(tdp, buf, size) \ + mac_lld_write_transmit_descriptor(tdp, buf, size) + +/** + * @brief Reads from a receive descriptor's stream. + * + * @param[in] rdp pointer to a @p MACReceiveDescriptor structure + * @param[in] buf pointer to the buffer that will receive the read data + * @param[in] size number of bytes to be read + * @return The number of bytes read from the descriptor's stream, + * this value can be less than the amount specified in the + * parameter @p size if there are no more bytes to read. + * + * @api + */ +#define macReadReceiveDescriptor(rdp, buf, size) \ + mac_lld_read_receive_descriptor(rdp, buf, size) + +#if MAC_USE_ZERO_COPY || defined(__DOXYGEN__) +/** + * @brief Returns a pointer to the next transmit buffer in the descriptor + * chain. + * @note The API guarantees that enough buffers can be requested to fill + * a whole frame. + * + * @param[in] tdp pointer to a @p MACTransmitDescriptor structure + * @param[in] size size of the requested buffer. Specify the frame size + * on the first call then scale the value down subtracting + * the amount of data already copied into the previous + * buffers. + * @param[out] sizep pointer to variable receiving the real buffer size. + * The returned value can be less than the amount + * requested, this means that more buffers must be + * requested in order to fill the frame data entirely. + * @return Pointer to the returned buffer. + * + * @api + */ +#define macGetNextTransmitBuffer(tdp, size, sizep) \ + mac_lld_get_next_transmit_buffer(tdp, size, sizep) + +/** + * @brief Returns a pointer to the next receive buffer in the descriptor + * chain. + * @note The API guarantees that the descriptor chain contains a whole + * frame. + * + * @param[in] rdp pointer to a @p MACReceiveDescriptor structure + * @param[out] sizep pointer to variable receiving the buffer size, it is + * zero when the last buffer has already been returned. + * @return Pointer to the returned buffer. + * @retval NULL if the buffer chain has been entirely scanned. + * + * @api + */ +#define macGetNextReceiveBuffer(rdp, sizep) \ + mac_lld_get_next_receive_buffer(rdp, sizep) +#endif /* MAC_USE_ZERO_COPY */ +/** @} */ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + void macInit(void); + void macObjectInit(MACDriver *macp); + void macStart(MACDriver *macp, const MACConfig *config); + void macStop(MACDriver *macp); + void macSetAddress(MACDriver *macp, const uint8_t *p); + msg_t macWaitTransmitDescriptor(MACDriver *macp, + MACTransmitDescriptor *tdp, + systime_t time); + void macReleaseTransmitDescriptor(MACTransmitDescriptor *tdp); + msg_t macWaitReceiveDescriptor(MACDriver *macp, + MACReceiveDescriptor *rdp, + systime_t time); + void macReleaseReceiveDescriptor(MACReceiveDescriptor *rdp); + bool_t macPollLinkStatus(MACDriver *macp); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_MAC */ + +#endif /* _MAC_H_ */ + +/** @} */ diff --git a/os/hal/include/mii.h b/os/hal/include/mii.h new file mode 100644 index 000000000..d4b65da54 --- /dev/null +++ b/os/hal/include/mii.h @@ -0,0 +1,162 @@ +/* + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010, + 2011,2012,2013 Giovanni Di Sirio. + + This file is part of ChibiOS/RT. + + ChibiOS/RT is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/RT is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/*-* + * @file mii.h + * @brief MII Driver macros and structures. + * + * @addtogroup MII + * @{ + */ + +#ifndef _MII_H_ +#define _MII_H_ + +/* + * Generic MII registers. Note, not all registers are present on all PHY + * devices and some extra registers may be present. + */ +#define MII_BMCR 0x00 /**< Basic mode control register. */ +#define MII_BMSR 0x01 /**< Basic mode status register. */ +#define MII_PHYSID1 0x02 /**< PHYS ID 1. */ +#define MII_PHYSID2 0x03 /**< PHYS ID 2. */ +#define MII_ADVERTISE 0x04 /**< Advertisement control reg. */ +#define MII_LPA 0x05 /**< Link partner ability reg. */ +#define MII_EXPANSION 0x06 /**< Expansion register. */ +#define MII_ANNPTR 0x07 /**< 1000BASE-T control. */ +#define MII_CTRL1000 0x09 /**< 1000BASE-T control. */ +#define MII_STAT1000 0x0a /**< 1000BASE-T status. */ +#define MII_ESTATUS 0x0f /**< Extended Status. */ +#define MII_PHYSTS 0x10 /**< PHY Status register. */ +#define MII_MICR 0x11 /**< MII Interrupt ctrl register. */ +#define MII_DCOUNTER 0x12 /**< Disconnect counter. */ +#define MII_FCSCOUNTER 0x13 /**< False carrier counter. */ +#define MII_NWAYTEST 0x14 /**< N-way auto-neg test reg. */ +#define MII_RERRCOUNTER 0x15 /**< Receive error counter. */ +#define MII_SREVISION 0x16 /**< Silicon revision. */ +#define MII_RESV1 0x17 /**< Reserved. */ +#define MII_LBRERROR 0x18 /**< Lpback, rx, bypass error. */ +#define MII_PHYADDR 0x19 /**< PHY address. */ +#define MII_RESV2 0x1a /**< Reserved. */ +#define MII_TPISTATUS 0x1b /**< TPI status for 10Mbps. */ +#define MII_NCONFIG 0x1c /**< Network interface config. */ + +/* + * Basic mode control register. + */ +#define BMCR_RESV 0x007f /**< Unused. */ +#define BMCR_CTST 0x0080 /**< Collision test. */ +#define BMCR_FULLDPLX 0x0100 /**< Full duplex. */ +#define BMCR_ANRESTART 0x0200 /**< Auto negotiation restart. */ +#define BMCR_ISOLATE 0x0400 /**< Disconnect DP83840 from MII. */ +#define BMCR_PDOWN 0x0800 /**< Powerdown. */ +#define BMCR_ANENABLE 0x1000 /**< Enable auto negotiation. */ +#define BMCR_SPEED100 0x2000 /**< Select 100Mbps. */ +#define BMCR_LOOPBACK 0x4000 /**< TXD loopback bit. */ +#define BMCR_RESET 0x8000 /**< Reset. */ + +/* + * Basic mode status register. + */ +#define BMSR_ERCAP 0x0001 /**< Ext-reg capability. */ +#define BMSR_JCD 0x0002 /**< Jabber detected. */ +#define BMSR_LSTATUS 0x0004 /**< Link status. */ +#define BMSR_ANEGCAPABLE 0x0008 /**< Able to do auto-negotiation. */ +#define BMSR_RFAULT 0x0010 /**< Remote fault detected. */ +#define BMSR_ANEGCOMPLETE 0x0020 /**< Auto-negotiation complete. */ +#define BMSR_MFPRESUPPCAP 0x0040 /**< Able to suppress preamble. */ +#define BMSR_RESV 0x0780 /**< Unused. */ +#define BMSR_10HALF 0x0800 /**< Can do 10mbps, half-duplex. */ +#define BMSR_10FULL 0x1000 /**< Can do 10mbps, full-duplex. */ +#define BMSR_100HALF 0x2000 /**< Can do 100mbps, half-duplex. */ +#define BMSR_100FULL 0x4000 /**< Can do 100mbps, full-duplex. */ +#define BMSR_100BASE4 0x8000 /**< Can do 100mbps, 4k packets. */ + +/* + * Advertisement control register. + */ +#define ADVERTISE_SLCT 0x001f /**< Selector bits. */ +#define ADVERTISE_CSMA 0x0001 /**< Only selector supported. */ +#define ADVERTISE_10HALF 0x0020 /**< Try for 10mbps half-duplex. */ +#define ADVERTISE_10FULL 0x0040 /**< Try for 10mbps full-duplex. */ +#define ADVERTISE_100HALF 0x0080 /**< Try for 100mbps half-duplex. */ +#define ADVERTISE_100FULL 0x0100 /**< Try for 100mbps full-duplex. */ +#define ADVERTISE_100BASE4 0x0200 /**< Try for 100mbps 4k packets. */ +#define ADVERTISE_PAUSE_CAP 0x0400 /**< Try for pause. */ +#define ADVERTISE_PAUSE_ASYM 0x0800 /**< Try for asymetric pause. */ +#define ADVERTISE_RESV 0x1000 /**< Unused. */ +#define ADVERTISE_RFAULT 0x2000 /**< Say we can detect faults. */ +#define ADVERTISE_LPACK 0x4000 /**< Ack link partners response. */ +#define ADVERTISE_NPAGE 0x8000 /**< Next page bit. */ + +#define ADVERTISE_FULL (ADVERTISE_100FULL | ADVERTISE_10FULL | \ + ADVERTISE_CSMA) +#define ADVERTISE_ALL (ADVERTISE_10HALF | ADVERTISE_10FULL | \ + ADVERTISE_100HALF | ADVERTISE_100FULL) + +/* + * Link partner ability register. + */ +#define LPA_SLCT 0x001f /**< Same as advertise selector. */ +#define LPA_10HALF 0x0020 /**< Can do 10mbps half-duplex. */ +#define LPA_10FULL 0x0040 /**< Can do 10mbps full-duplex. */ +#define LPA_100HALF 0x0080 /**< Can do 100mbps half-duplex. */ +#define LPA_100FULL 0x0100 /**< Can do 100mbps full-duplex. */ +#define LPA_100BASE4 0x0200 /**< Can do 100mbps 4k packets. */ +#define LPA_PAUSE_CAP 0x0400 /**< Can pause. */ +#define LPA_PAUSE_ASYM 0x0800 /**< Can pause asymetrically. */ +#define LPA_RESV 0x1000 /**< Unused. */ +#define LPA_RFAULT 0x2000 /**< Link partner faulted. */ +#define LPA_LPACK 0x4000 /**< Link partner acked us. */ +#define LPA_NPAGE 0x8000 /**< Next page bit. */ + +#define LPA_DUPLEX (LPA_10FULL | LPA_100FULL) +#define LPA_100 (LPA_100FULL | LPA_100HALF | LPA_100BASE4) + +/* + * Expansion register for auto-negotiation. + */ +#define EXPANSION_NWAY 0x0001 /**< Can do N-way auto-nego. */ +#define EXPANSION_LCWP 0x0002 /**< Got new RX page code word. */ +#define EXPANSION_ENABLENPAGE 0x0004 /**< This enables npage words. */ +#define EXPANSION_NPCAPABLE 0x0008 /**< Link partner supports npage. */ +#define EXPANSION_MFAULTS 0x0010 /**< Multiple faults detected. */ +#define EXPANSION_RESV 0xffe0 /**< Unused. */ + +/* + * N-way test register. + */ +#define NWAYTEST_RESV1 0x00ff /**< Unused. */ +#define NWAYTEST_LOOPBACK 0x0100 /**< Enable loopback for N-way. */ +#define NWAYTEST_RESV2 0xfe00 /**< Unused. */ + +/* + * PHY identifiers. + */ +#define MII_DM9161_ID 0x0181b8a0 +#define MII_AM79C875_ID 0x00225540 +#define MII_KS8721_ID 0x00221610 +#define MII_STE101P_ID 0x00061C50 +#define MII_DP83848I_ID 0x20005C90 +#define MII_LAN8710A_ID 0x0007C0F1 + +#endif /* _MII_H_ */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/mac_lld.c b/os/hal/ports/STM32/LLD/mac_lld.c index daddf27b6..92593426c 100644 --- a/os/hal/ports/STM32/LLD/mac_lld.c +++ b/os/hal/ports/STM32/LLD/mac_lld.c @@ -123,9 +123,10 @@ static void mii_find_phy(MACDriver *macp) { uint32_t i; #if STM32_MAC_PHY_TIMEOUT > 0 - halrtcnt_t start = halGetCounterValue(); - halrtcnt_t timeout = start + MS2RTT(STM32_MAC_PHY_TIMEOUT); - while (halIsCounterWithin(start, timeout)) { + rtcnt_t start = chSysGetRealtimeCounterX(); + rtcnt_t timeout = start + MS2RTC(STM32_HCLK,STM32_MAC_PHY_TIMEOUT); + rtcnt_t time = start; + while (chSysIsCounterWithinX(time, start, timeout)) { #endif for (i = 0; i < 31; i++) { macp->phyaddr = i << 11; @@ -136,10 +137,11 @@ static void mii_find_phy(MACDriver *macp) { } } #if STM32_MAC_PHY_TIMEOUT > 0 + time = chSysGetRealtimeCounterX(); } #endif /* Wrong or defective board.*/ - chSysHalt(); + osalSysHalt("MAC failure"); } #endif @@ -183,19 +185,19 @@ CH_IRQ_HANDLER(ETH_IRQHandler) { if (dmasr & ETH_DMASR_RS) { /* Data Received.*/ - chSysLockFromIsr(); + osalSysLockFromISR(); chSemResetI(ÐD1.rdsem, 0); #if MAC_USE_EVENTS chEvtBroadcastI(ÐD1.rdevent); #endif - chSysUnlockFromIsr(); + osalSysUnlockFromISR(); } if (dmasr & ETH_DMASR_TS) { /* Data Transmitted.*/ - chSysLockFromIsr(); + osalSysLockFromISR(); chSemResetI(ÐD1.tdsem, 0); - chSysUnlockFromIsr(); + osalSysUnlockFromISR(); } CH_IRQ_EPILOGUE(); @@ -266,7 +268,7 @@ void mac_lld_init(void) { /* PHY soft reset procedure.*/ mii_write(ÐD1, MII_BMCR, BMCR_RESET); #if defined(BOARD_PHY_RESET_DELAY) - halPolledDelay(BOARD_PHY_RESET_DELAY); + chSysPolledDelayX(BOARD_PHY_RESET_DELAY); #endif while (mii_read(ÐD1, MII_BMCR) & BMCR_RESET) ; @@ -308,8 +310,7 @@ void mac_lld_start(MACDriver *macp) { #endif /* ISR vector enabled.*/ - nvicEnableVector(ETH_IRQn, - CORTEX_PRIORITY_MASK(STM32_MAC_ETH1_IRQ_PRIORITY)); + nvicEnableVector(ETH_IRQn, STM32_MAC_ETH1_IRQ_PRIORITY); #if STM32_MAC_ETH1_CHANGE_PHY_STATE /* PHY in power up mode.*/ @@ -405,9 +406,9 @@ msg_t mac_lld_get_transmit_descriptor(MACDriver *macp, stm32_eth_tx_descriptor_t *tdes; if (!macp->link_up) - return RDY_TIMEOUT; + return MSG_TIMEOUT; - chSysLock(); + osalSysLock(); /* Get Current TX descriptor.*/ tdes = macp->txptr; @@ -415,8 +416,8 @@ msg_t mac_lld_get_transmit_descriptor(MACDriver *macp, /* 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; + osalSysUnlock(); + return MSG_TIMEOUT; } /* Marks the current descriptor as locked using a reserved bit.*/ @@ -425,14 +426,14 @@ msg_t mac_lld_get_transmit_descriptor(MACDriver *macp, /* Next TX descriptor to use.*/ macp->txptr = (stm32_eth_tx_descriptor_t *)tdes->tdes3; - chSysUnlock(); + osalSysUnlock(); /* Set the buffer size and configuration.*/ tdp->offset = 0; tdp->size = STM32_MAC_BUFFERS_SIZE; tdp->physdesc = tdes; - return RDY_OK; + return MSG_OK; } /** @@ -445,11 +446,10 @@ msg_t mac_lld_get_transmit_descriptor(MACDriver *macp, */ void mac_lld_release_transmit_descriptor(MACTransmitDescriptor *tdp) { - chDbgAssert(!(tdp->physdesc->tdes0 & STM32_TDES0_OWN), - "mac_lld_release_transmit_descriptor(), #1", + osalDbgAssert(!(tdp->physdesc->tdes0 & STM32_TDES0_OWN), "attempt to release descriptor already owned by DMA"); - chSysLock(); + osalSysLock(); /* Unlocks the descriptor and returns it to the DMA engine.*/ tdp->physdesc->tdes1 = tdp->offset; @@ -463,7 +463,7 @@ void mac_lld_release_transmit_descriptor(MACTransmitDescriptor *tdp) { ETH->DMATPDR = ETH_DMASR_TBUS; /* Any value is OK.*/ } - chSysUnlock(); + osalSysUnlock(); } /** @@ -481,7 +481,7 @@ msg_t mac_lld_get_receive_descriptor(MACDriver *macp, MACReceiveDescriptor *rdp) { stm32_eth_rx_descriptor_t *rdes; - chSysLock(); + osalSysLock(); /* Get Current RX descriptor.*/ rdes = macp->rxptr; @@ -501,8 +501,8 @@ msg_t mac_lld_get_receive_descriptor(MACDriver *macp, rdp->physdesc = rdes; macp->rxptr = (stm32_eth_rx_descriptor_t *)rdes->rdes3; - chSysUnlock(); - return RDY_OK; + osalSysUnlock(); + return MSG_OK; } /* Invalid frame found, purging.*/ rdes->rdes0 = STM32_RDES0_OWN; @@ -512,8 +512,8 @@ msg_t mac_lld_get_receive_descriptor(MACDriver *macp, /* Next descriptor to check.*/ macp->rxptr = rdes; - chSysUnlock(); - return RDY_TIMEOUT; + osalSysUnlock(); + return MSG_TIMEOUT; } /** @@ -527,11 +527,10 @@ msg_t mac_lld_get_receive_descriptor(MACDriver *macp, */ void mac_lld_release_receive_descriptor(MACReceiveDescriptor *rdp) { - chDbgAssert(!(rdp->physdesc->rdes0 & STM32_RDES0_OWN), - "mac_lld_release_receive_descriptor(), #1", + osalDbgAssert(!(rdp->physdesc->rdes0 & STM32_RDES0_OWN), "attempt to release descriptor already owned by DMA"); - chSysLock(); + osalSysLock(); /* Give buffer back to the Ethernet DMA.*/ rdp->physdesc->rdes0 = STM32_RDES0_OWN; @@ -542,7 +541,7 @@ void mac_lld_release_receive_descriptor(MACReceiveDescriptor *rdp) { ETH->DMARPDR = ETH_DMASR_RBUS; /* Any value is OK.*/ } - chSysUnlock(); + osalSysUnlock(); } /** @@ -632,8 +631,7 @@ size_t mac_lld_write_transmit_descriptor(MACTransmitDescriptor *tdp, uint8_t *buf, size_t size) { - chDbgAssert(!(tdp->physdesc->tdes0 & STM32_TDES0_OWN), - "mac_lld_write_transmit_descriptor(), #1", + osalDbgAssert(!(tdp->physdesc->tdes0 & STM32_TDES0_OWN), "attempt to write descriptor already owned by DMA"); if (size > tdp->size - tdp->offset) @@ -663,8 +661,7 @@ size_t mac_lld_read_receive_descriptor(MACReceiveDescriptor *rdp, uint8_t *buf, size_t size) { - chDbgAssert(!(rdp->physdesc->rdes0 & STM32_RDES0_OWN), - "mac_lld_read_receive_descriptor(), #1", + osalDbgAssert(!(rdp->physdesc->rdes0 & STM32_RDES0_OWN), "attempt to read descriptor already owned by DMA"); if (size > rdp->size - rdp->offset) diff --git a/os/hal/ports/STM32/LLD/mac_lld.h b/os/hal/ports/STM32/LLD/mac_lld.h index 34b724e07..7c00d4927 100644 --- a/os/hal/ports/STM32/LLD/mac_lld.h +++ b/os/hal/ports/STM32/LLD/mac_lld.h @@ -245,16 +245,16 @@ struct MACDriver { /** * @brief Transmit semaphore. */ - Semaphore tdsem; + semaphore_t tdsem; /** * @brief Receive semaphore. */ - Semaphore rdsem; + semaphore_t rdsem; #if MAC_USE_EVENTS || defined(__DOXYGEN__) /** * @brief Receive event. */ - EventSource rdevent; + event_source_t rdevent; #endif /* End of the mandatory fields.*/ /** diff --git a/os/hal/src/mac.c b/os/hal/src/mac.c new file mode 100644 index 000000000..ec8e08921 --- /dev/null +++ b/os/hal/src/mac.c @@ -0,0 +1,268 @@ +/* + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010, + 2011,2012,2013 Giovanni Di Sirio. + + This file is part of ChibiOS/RT. + + ChibiOS/RT is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/RT is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file mac.c + * @brief MAC Driver code. + * + * @addtogroup MAC + * @{ + */ + +#include "hal.h" + +#if HAL_USE_MAC || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +#if MAC_USE_ZERO_COPY && !MAC_SUPPORTS_ZERO_COPY +#error "MAC_USE_ZERO_COPY not supported by this implementation" +#endif + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief MAC Driver initialization. + * @note This function is implicitly invoked by @p halInit(), there is + * no need to explicitly initialize the driver. + * + * @init + */ +void macInit(void) { + + mac_lld_init(); +} + +/** + * @brief Initialize the standard part of a @p MACDriver structure. + * + * @param[out] macp pointer to the @p MACDriver object + * + * @init + */ +void macObjectInit(MACDriver *macp) { + + macp->state = MAC_STOP; + macp->config = NULL; + chSemObjectInit(&macp->tdsem, 0); + chSemObjectInit(&macp->rdsem, 0); +#if MAC_USE_EVENTS + chEvtObjectInit(&macp->rdevent); +#endif +} + +/** + * @brief Configures and activates the MAC peripheral. + * + * @param[in] macp pointer to the @p MACDriver object + * @param[in] config pointer to the @p MACConfig object + * + * @api + */ +void macStart(MACDriver *macp, const MACConfig *config) { + + osalDbgCheck((macp != NULL) && (config != NULL)); + + osalSysLock(); + osalDbgAssert(macp->state == MAC_STOP, + "invalid state"); + macp->config = config; + mac_lld_start(macp); + macp->state = MAC_ACTIVE; + osalSysUnlock(); +} + +/** + * @brief Deactivates the MAC peripheral. + * + * @param[in] macp pointer to the @p MACDriver object + * + * @api + */ +void macStop(MACDriver *macp) { + + osalDbgCheck(macp != NULL); + + osalSysLock(); + osalDbgAssert((macp->state == MAC_STOP) || (macp->state == MAC_ACTIVE), + "invalid state"); + mac_lld_stop(macp); + macp->state = MAC_STOP; + osalSysUnlock(); +} + +/** + * @brief Allocates a transmission descriptor. + * @details One of the available transmission descriptors is locked and + * returned. If a descriptor is not currently available then the + * invoking thread is queued until one is freed. + * + * @param[in] macp pointer to the @p MACDriver object + * @param[out] tdp pointer to a @p MACTransmitDescriptor structure + * @param[in] time the number of ticks before the operation timeouts, + * the following special values are allowed: + * - @a TIME_IMMEDIATE immediate timeout. + * - @a TIME_INFINITE no timeout. + * . + * @return The operation status. + * @retval RDY_OK the descriptor was obtained. + * @retval RDY_TIMEOUT the operation timed out, descriptor not initialized. + * + * @api + */ +msg_t macWaitTransmitDescriptor(MACDriver *macp, + MACTransmitDescriptor *tdp, + systime_t time) { + msg_t msg; + systime_t now; + + osalDbgCheck((macp != NULL) && (tdp != NULL)); + osalDbgAssert(macp->state == MAC_ACTIVE, "not active"); + + while (((msg = mac_lld_get_transmit_descriptor(macp, tdp)) != MSG_OK) && + (time > 0)) { + osalSysLock(); + now = osalOsGetSystemTimeX(); + if ((msg = chSemWaitTimeoutS(&macp->tdsem, time)) == MSG_TIMEOUT) { + osalSysUnlock(); + break; + } + if (time != TIME_INFINITE) + time -= (osalOsGetSystemTimeX() - now); + osalSysUnlock(); + } + return msg; +} + +/** + * @brief Releases a transmit descriptor and starts the transmission of the + * enqueued data as a single frame. + * + * @param[in] tdp the pointer to the @p MACTransmitDescriptor structure + * + * @api + */ +void macReleaseTransmitDescriptor(MACTransmitDescriptor *tdp) { + + osalDbgCheck(tdp != NULL); + + mac_lld_release_transmit_descriptor(tdp); +} + +/** + * @brief Waits for a received frame. + * @details Stops until a frame is received and buffered. If a frame is + * not immediately available then the invoking thread is queued + * until one is received. + * + * @param[in] macp pointer to the @p MACDriver object + * @param[out] rdp pointer to a @p MACReceiveDescriptor structure + * @param[in] time the number of ticks before the operation timeouts, + * the following special values are allowed: + * - @a TIME_IMMEDIATE immediate timeout. + * - @a TIME_INFINITE no timeout. + * . + * @return The operation status. + * @retval RDY_OK the descriptor was obtained. + * @retval RDY_TIMEOUT the operation timed out, descriptor not initialized. + * + * @api + */ +msg_t macWaitReceiveDescriptor(MACDriver *macp, + MACReceiveDescriptor *rdp, + systime_t time) { + msg_t msg; + systime_t now; + + osalDbgCheck((macp != NULL) && (rdp != NULL)); + osalDbgAssert(macp->state == MAC_ACTIVE, "not active"); + + while (((msg = mac_lld_get_receive_descriptor(macp, rdp)) != MSG_OK) && + (time > 0)) { + osalSysLock(); + now = osalOsGetSystemTimeX(); + if ((msg = chSemWaitTimeoutS(&macp->rdsem, time)) == MSG_TIMEOUT) { + osalSysUnlock(); + break; + } + if (time != TIME_INFINITE) + time -= (osalOsGetSystemTimeX() - now); + osalSysUnlock(); + } + return msg; +} + +/** + * @brief Releases a receive descriptor. + * @details The descriptor and its buffer are made available for more incoming + * frames. + * + * @param[in] rdp the pointer to the @p MACReceiveDescriptor structure + * + * @api + */ +void macReleaseReceiveDescriptor(MACReceiveDescriptor *rdp) { + + osalDbgCheck(rdp != NULL); + + mac_lld_release_receive_descriptor(rdp); +} + +/** + * @brief Updates and returns the link status. + * + * @param[in] macp pointer to the @p MACDriver object + * @return The link status. + * @retval TRUE if the link is active. + * @retval FALSE if the link is down. + * + * @api + */ +bool_t macPollLinkStatus(MACDriver *macp) { + + osalDbgCheck(macp != NULL); + osalDbgAssert(macp->state == MAC_ACTIVE, "not active"); + + return mac_lld_poll_link_status(macp); +} + +#endif /* HAL_USE_MAC */ + +/** @} */ -- cgit v1.2.3