Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 5 of 5

Thread: Disabling Ethernet without freezing

  1. #1
    Senior Member
    Join Date
    Mar 2017
    Location
    Oakland, CA, USA
    Posts
    313

    Disabling Ethernet without freezing

    When Ethernet is initialized in QNEthernet, the Ethernet clock in the the clock gating register CCM_CCGR1 (CG5) is enabled. I know that when a feature on an ARM processor is used without first having its clock enabled, things can freeze.

    The issue I'm having is that when I disable Ethernet by turning off the appropriate bits in CCM_CCGR1, the system freezes. Are there specific steps I need to follow so that I can safely disable the clock? Maybe it's something as simple as undoing some of the configuration steps? I'm already disabling the PLL before shutting down the clock, but no luck.

    Here's what I'm doing:
    Code:
      // Stop the PLL
      CCM_ANALOG_PLL_ENET_SET = CCM_ANALOG_PLL_ENET_BYPASS;
      CCM_ANALOG_PLL_ENET_CLR = CCM_ANALOG_PLL_ENET_ENABLE;
      CCM_ANALOG_PLL_ENET_SET = CCM_ANALOG_PLL_ENET_POWERDOWN;
    
      // Disable the clock for ENET
      CCM_CCGR1 &= ~CCM_CCGR1_ENET(CCM_CCGR_ON);

  2. #2
    Senior Member
    Join Date
    Mar 2017
    Location
    Oakland, CA, USA
    Posts
    313
    I solved this by properly removing the netif ext callback (additions and removals were not matched). It doesn’t freeze, but now DHCP can’t get an IP address when Ethernet is restarted.

  3. #3
    Senior Member
    Join Date
    Mar 2017
    Location
    Oakland, CA, USA
    Posts
    313
    It turned out that the solution to the DHCP issue was to not "detach" or shut down the EventResponder (i.e. it's only "attached" once). When it needs to stop, a Boolean "active" variable is set to false. When it needs to start up again, that variable is set to true and then `triggerEvent()` is called.

    Previously, the function was no longer getting called once it was detached and then reattached later. That's why no DHCP requests were getting through. EthernetClass::loop() was never getting called.

  4. #4
    Senior Member
    Join Date
    Dec 2016
    Location
    Montreal, Canada
    Posts
    3,871
    normally you disable the peripheral before turning off it's clock, also, if your sketch still runs remnants of ethernet code while the peripheral/clocks are disabled, then yes it will crash. You could add registry checks to see if the peripheral is enabled, if not, just return the function with an error, and it *shouldn't* crash.

  5. #5
    Senior Member
    Join Date
    Mar 2017
    Location
    Oakland, CA, USA
    Posts
    313
    Currently, I'm shutting down the PHY, disabling the PLL (just re-added), and then disabling the ENET clock.
    Here's the link to the code (enet_deinit()): https://github.com/ssilverman/QNEthe...wip_t41.c#L572
    Here's the Ethernet.end() function (calls enet_deinit()): https://github.com/ssilverman/QNEthe...ernet.cpp#L184

    @tonton81 Does this look right to you? Do you suggest any changes, additions, or removals?

    Here's my test code showing the procedure doesn't hang (if you try it, get the latest release from GitHub):
    Code:
    #include <QNEthernet.h>
    
    using namespace qindesign::network;
    
    extern Print *stdPrint;
    
    constexpr uint32_t kDHCPTimeout = 10000;
    
    void setup() {
      Serial.begin(115200);
      while (!Serial && millis() < 4000) {
        // Wait for Serial to initialize
      }
      stdPrint = &Serial;
      delay(2000);
      printf("Starting...\n");
    
      Ethernet.onLinkState([](bool state) {
        printf("Link %s\n", state ? "ON" : "OFF");
      });
    
      Ethernet.onAddressChanged([]() {
        printf("Address changed\n");
    
        IPAddress ip = Ethernet.localIP();
        printf("    Local IP    = %d.%d.%d.%d\n",
               ip[0], ip[1], ip[2], ip[3]);
        ip = Ethernet.subnetMask();
        printf("    Subnet mask = %u.%u.%u.%u\n",
               ip[0], ip[1], ip[2], ip[3]);
        ip = Ethernet.gatewayIP();
        printf("    Gateway     = %u.%u.%u.%u\n",
               ip[0], ip[1], ip[2], ip[3]);
        ip = Ethernet.dnsServerIP();
        printf("    DNS         = %u.%u.%u.%u\n",
               ip[0], ip[1], ip[2], ip[3]);
      });
    
      uint8_t mac[6];
      Ethernet.macAddress(mac);
      printf("MAC = %02x:%02x:%02x:%02x:%02x:%02x\n",
             mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
    
      for (int i = 0; i < 4; i++) {
        Serial.println("Starting Ethernet with DHCP...");
        if (!Ethernet.begin()) {
          Serial.println("Failed to start Ethernet");
          continue;
        }
        if (!Ethernet.waitForLocalIP(kDHCPTimeout)) {
          Serial.println("Failed to get IP address from DHCP");
        }
    
        printf("Ending Ethernet...\n");
        Ethernet.end();
        printf("Done ending Ethernet.\n");
      }
    }
    
    void loop() {
      // Nothing
    }

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •