{"action":"created","issue":{"url":"https://api.github.com/repos/andysworkshop/stm32plus/issues/108","labels_url":"https://api.github.com/repos/andysworkshop/stm32plus/issues/108/labels{/name}","comments_url":"https://api.github.com/repos/andysworkshop/stm32plus/issues/108/comments","events_url":"https://api.github.com/repos/andysworkshop/stm32plus/issues/108/events","html_url":"https://github.com/andysworkshop/stm32plus/issues/108","id":68271524,"number":108,"title":"Ethernet PHY Support ","user":{"login":"danielschramm","id":7165994,"avatar_url":"https://avatars.githubusercontent.com/u/7165994?v=3","gravatar_id":"","url":"https://api.github.com/users/danielschramm","html_url":"https://github.com/danielschramm","followers_url":"https://api.github.com/users/danielschramm/followers","following_url":"https://api.github.com/users/danielschramm/following{/other_user}","gists_url":"https://api.github.com/users/danielschramm/gists{/gist_id}","starred_url":"https://api.github.com/users/danielschramm/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/danielschramm/subscriptions","organizations_url":"https://api.github.com/users/danielschramm/orgs","repos_url":"https://api.github.com/users/danielschramm/repos","events_url":"https://api.github.com/users/danielschramm/events{/privacy}","received_events_url":"https://api.github.com/users/danielschramm/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":2,"created_at":"2015-04-14T06:06:53Z","updated_at":"2015-04-14T14:34:16Z","closed_at":null,"body":"Hello,\r\n\r\nOlimex changed the PHY on their STM32-E407 boards to LAN8710A, which currently is not supported by stm32plus.\r\nI attached my quick and dirty implementation for this chip to this issue. Please review and include it into the distribution.\r\n\r\nThanks,\r\n\r\nDaniel\r\n\r\n\r\n\r\n\r\n\r\n\r\n#pragma once\r\n\r\n\r\nnamespace stm32plus {\r\n  namespace net {\r\n\r\n    /**\r\n     * Class for the  LAN8710A PHY.\r\n     */\r\n\r\n    class LAN8710A : public PhyBase {\r\n\r\n      public:\r\n\r\n        /**\r\n         * Custom registers for this PHY\r\n         */\r\n\r\n        enum {\r\n        \tPHY_BasicControl = 0,\r\n        \tPHY_BasicStatus = 1,\r\n        \tPHY_Identifier1 = 2,\r\n        \tPHY_Identifier2 = 3,\r\n        \tPHY_AutoNegotiationAdvertisement = 4,\r\n        \tPHY_AutoNegotiationLinkPartnerAbility = 5,\r\n        \tPHY_AutoNegotiationExpansion = 6,\r\n        \tPHY_ModeControlStatus = 17,\r\n        \tPHY_SpecialModes = 18,\r\n        \tPHY_SymbolErrorCounter = 26,\r\n        \tPHY_ControlStatusIndication = 27,\r\n        \tPHY_InterruptSource = 29,\r\n        \tPHY_InterruptMask = 30,\r\n        \tPHY_SpecialControlStatus = 31\r\n        };\r\n\r\n        /**\r\n         * Interrupt bits\r\n         */\r\n\r\n        enum {\r\n          INTERRUPT_ENERGYON              \t\t= 0x80,\r\n          INTERRUPT_AUTO_NEGOTIATION        \t= 0x40,\r\n          INTERRUPT_REMOTE_FAULT\t\t\t\t= 0x20,\r\n          INTERRUPT_LINK_DOWN\t\t\t    \t= 0x10,\r\n          INTERRUPT_AUTO_NEGOTIATION_LP_ACK \t= 0x8,\r\n          INTERRUPT_PARALLEL_FAULT         \t \t= 0x4,\r\n          INTERRUPT_AUTO_NEGOTIATION_PAGE_RX\t= 0x2,\r\n          INTERRUPT_ALL                       \t= 0xf7\r\n        };\r\n\r\n\r\n        /**\r\n         * Configuration parameters for the LAN8710A\r\n         */\r\n\r\n        struct Parameters : virtual PhyBase::Parameters {\r\n\r\n          /**\r\n           * Constructor: set defaults\r\n           */\r\n\r\n          Parameters() {\r\n            phy_resetDelay      = 2;        // wait 2ms after reset is asserted\r\n            phy_speedStatusBit  = 0x0002;   // link speed bit in status word\r\n            phy_duplexStatusBit = 0x0004;   // full duplex bit in status word\r\n          }\r\n        };\r\n\r\n        bool phyEnableInterrupts(uint8_t interruptMask) const;\r\n        bool phyDisableInterrupts(uint8_t interruptMask) const;\r\n\r\n        bool phyIs100M(bool& is100) const;\r\n        bool phyIsFullDuplex(bool& isFull) const;\r\n        bool phyClearPendingInterrupts() const;\r\n        bool phyGetPendingInterrupts(uint16_t& interrupts) const;\r\n\r\n        // hard reset is supported through the PhyHardReset feature class\r\n\r\n        void phyHardReset(GpioPinRef& pin) const;\r\n\r\n        bool initialise(Parameters& params,NetworkUtilityObjects& netutils);\r\n        bool startup();\r\n    };\r\n\r\n\r\n    /**\r\n     * Initialise the PHY class\r\n     * @param params The parameters class\r\n     * @param netutils The network utilities\r\n     * @return true if it worked\r\n     */\r\n\r\n    inline bool LAN8710A::initialise(Parameters& params,NetworkUtilityObjects& netutils) {\r\n      return PhyBase::initialise(params,netutils);\r\n    }\r\n\r\n\r\n    /**\r\n     * Startup\r\n     * @return true if it worked\r\n     */\r\n\r\n    inline bool LAN8710A::startup() {\r\n      return PhyBase::startup();\r\n    }\r\n\r\n\r\n    /**\r\n     * Check if we are linked at 100Mb/s\r\n     * @param is100 true if we are at 100Mb/s\r\n     * @return true if it worked\r\n     */\r\n\r\n    inline bool LAN8710A::phyIs100M(bool& is100) const {\r\n\r\n      uint16_t value;\r\n\r\n      if(!phyReadRegister(PHY_BasicStatus,value))\r\n        return false;\r\n      is100=false;\r\n\t  if(value & (1<<9)) { // 100BASE-T2 Half Duplex\r\n\t\t  is100=true;\r\n\t  }\r\n\t  if(value & (1<<10)) { // 100BASE-T2 Full Duplex\r\n\t\t  is100=true;\r\n\t  }\r\n\t  if(value & (1<<13)) { // 100BASE-TX Half Duplex\r\n\t\t  is100=true;\r\n\t  }\r\n\t  if(value & (1<<14)) { // 100BASE-TX Full Duplex\r\n\t\t  is100=true;\r\n\t  }\r\n\t  if(value & (1<<15)) { // 100BASE-T4\r\n\t\t  is100=true;\r\n\t  }\r\n      return true;\r\n    }\r\n\r\n\r\n    /**\r\n     * Check if we are linked at full duplex\r\n     * @param is100 true if we are at 100Mb/s\r\n     * @return true if it worked\r\n     */\r\n\r\n    inline bool LAN8710A::phyIsFullDuplex(bool& isFull) const {\r\n\r\n      uint16_t value;\r\n\r\n      if(!phyReadRegister(PHY_BasicStatus,value))\r\n        return false;\r\n\r\n      isFull=false;\r\n\t  if(value & (1<<10)) { // 100BASE-T2 Full Duplex\r\n\t\t  isFull=true;\r\n\t  }\r\n\t  if(value & (1<<12)) { // 10BASE-T Full Duplex\r\n\t\t  isFull=true;\r\n\t  }\r\n\t  if(value & (1<<14)) { // 100BASE-TX Full Duplex\r\n\t\t  isFull=true;\r\n\t  }\r\n      return true;\r\n    }\r\n\r\n\r\n    /**\r\n     * Clear pending interrupt flags. On the LAN8710A reading the MISR register\r\n     * clears the pending interrupt flags\r\n     * @return true if it worked\r\n     */\r\n\r\n    inline bool LAN8710A::phyClearPendingInterrupts() const {\r\n      uint16_t value;\r\n      return phyReadRegister(PHY_InterruptSource,value);\r\n    }\r\n\r\n\r\n    /**\r\n     * Read the pending interrupts register to determine which ones have fired\r\n     * @param[out] interrupts The interrupt bitmask. Can be AND'ed with INTERRUPT_ values\r\n     * @return true if it worked\r\n     */\r\n\r\n    inline bool LAN8710A::phyGetPendingInterrupts(uint16_t& interrupts) const {\r\n\r\n      if(!phyReadRegister(PHY_InterruptSource,interrupts))\r\n        return false;\r\n\r\n//      // pending bits are in the upper byte, shift them down so that the INTERRUPT_* masks apply\r\n//\r\n//      interrupts>>=8;\r\n      return true;\r\n    }\r\n\r\n\r\n    /**\r\n     * Enable interrupts to be received on the Observable interface. This function merges\r\n     * the bits in interrupt mask into the register\r\n     * @param interruptMask The interrupts to enable (INTERRUPT_*)\r\n     * @return true if it worked\r\n     */\r\n\r\n    inline bool LAN8710A::phyEnableInterrupts(uint8_t interruptMask) const {\r\n      return\r\n          phySetRegisterBits(PHY_InterruptMask,interruptMask);\r\n//\t\t  &&\r\n//          phySetRegisterBits(PHY_InterruptSource,interruptMask);\r\n    }\r\n\r\n\r\n    /**\r\n     * Disable interrupts to be received on the Observable interface. This function masks out\r\n     * the bits in interrupt mask into the register\r\n     * @param interruptMask The interrupts to enable (INTERRUPT_*)\r\n     * @return true if it worked\r\n     */\r\n\r\n    inline bool LAN8710A::phyDisableInterrupts(uint8_t interruptMask) const {\r\n      return phyClearRegisterBits(PHY_InterruptMask,interruptMask);\r\n    }\r\n\r\n\r\n    /**\r\n     * Hard-reset the PHY by pulling the RESET pin low for 5ms. The datasheet\r\n     * indicates that 1us is the minimum between stable power and rising reset so\r\n     * we're playing safe.\r\n     * @param pin\r\n     */\r\n\r\n    inline void LAN8710A::phyHardReset(GpioPinRef& pin) const {\r\n      pin.reset();\r\n      MillisecondTimer::delay(5);\r\n      pin.set();\r\n    }\r\n  }\r\n}\r\n\r\n"},"comment":{"url":"https://api.github.com/repos/andysworkshop/stm32plus/issues/comments/92879094","html_url":"https://github.com/andysworkshop/stm32plus/issues/108#issuecomment-92879094","issue_url":"https://api.github.com/repos/andysworkshop/stm32plus/issues/108","id":92879094,"user":{"login":"mikepurvis","id":944666,"avatar_url":"https://avatars.githubusercontent.com/u/944666?v=3","gravatar_id":"","url":"https://api.github.com/users/mikepurvis","html_url":"https://github.com/mikepurvis","followers_url":"https://api.github.com/users/mikepurvis/followers","following_url":"https://api.github.com/users/mikepurvis/following{/other_user}","gists_url":"https://api.github.com/users/mikepurvis/gists{/gist_id}","starred_url":"https://api.github.com/users/mikepurvis/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mikepurvis/subscriptions","organizations_url":"https://api.github.com/users/mikepurvis/orgs","repos_url":"https://api.github.com/users/mikepurvis/repos","events_url":"https://api.github.com/users/mikepurvis/events{/privacy}","received_events_url":"https://api.github.com/users/mikepurvis/received_events","type":"User","site_admin":false},"created_at":"2015-04-14T14:34:16Z","updated_at":"2015-04-14T14:34:16Z","body":"Okay, your class here is working for me on both the 8710 and 8720. I can successfully run the net_dhcp and net_tcp_server examples. Thanks!"}}