0

I'm using a Nucleo F429ZI board and I wrote a sketch that enables a simple web-server:

#include <LwIP.h>
#include <STM32Ethernet.h>

const int WEB_PORT = 80;
EthernetServer server(WEB_PORT);
char buffer[1024];

void setup() 
{
    Serial.begin(115200);
    // define variables
    Ethernet.begin(localIP, netmask, dns, gateway);
    server.begin();
}

void loop() 
{
    processServer();
}

void processServer()
{
  String readString; 
  EthernetClient client = server.available();
  if (client) 
  {
    while (client.connected()) 
    {
      if (client.available()) 
      {
        char c = client.read();
        readString += c; 

        if (c == '\n')
        {
          if (readString.startsWith("GET"))
          {
            readString.remove(0, 4);
            int pos = readString.indexOf(' ');
            String path = readString.substring(0, pos);

            if (path == "/status") pageStatus(client);
            break;
          }
        }
      }
    }
    delay(1);
    client.stop();
  }
}

void pageStatus(EthernetClient client)
{
    sectionHeader(client, 2);
    client.println("<html>");
    client.println("<style>table{font-family: verdana, sans-serif;border-collapse: collapse;width: 30%;}");
    client.println("td, th{border: 1px solid #dddddd;text-align: left;padding: 8px;}tr:nth-child(even)");
    client.println("{background-color: #dddddd;}</style>");
    client.println("<table>");
    client.println("<tr><th>Servo</th><th>Position</th><th>Running</th><th>Initialized</th></tr>");

    for (int i = 0; i < getParamUInt8(P_SERVO_SIZE); i++) 
    {
        sprintf(buffer, "<tr><td>%u</td><td>%d</td><td>%s</td><td>%s</td></tr>", i + 1, (int16_t) _servo[i].current, _servo[i].ended ? "NO" : "YES", _servo[i].initialized ? "YES" : "NO" );
        client.println(buffer);
    }
    client.println("</table>");

    client.println("<br><hr><br>");

    client.println("<table>");
    client.println("<tr><th>Led</th><th>PWM</th><th>Running</th></tr>");

    for (int i = 0; i < getParamUInt8(P_LED_SIZE); i++) 
    {
        sprintf(buffer, "<tr><td>%u</td><td>%d</td><td>%s</td></tr>", i + 1, (int16_t) _led[i].pwm, _led[i].ended ? "NO" : "YES");
        client.println(buffer);
    }
    client.println("</table>");

    client.println("<br><hr><br>");

    client.println("<table>");
    client.println("<tr><th>Stepper</th><th>Position</th><th>Running</th></tr>");

    for (int i = 0; i < getParamUInt8(P_STEPPER_SIZE); i++) 
    {
        sprintf(buffer, "<tr><td>%u</td><td>%d</td><td>%s</td></tr>", i + 1, (int16_t) _stepper[i].stepper.getCurrentPositionInMillimeters(), _stepper[i].stepper.motionComplete() ? "NO" : "YES");
        client.println(buffer);
    }
    client.println("</table>");
    client.println("</html>");
}

void sectionHeader(EthernetClient client, int refresh)
{
    client.println("HTTP/1.1 200 OK");
    client.println("Content-Type: text/html");
    client.println("Connection: close");
    if (refresh) client.println("Refresh: 2"); 
    client.println();
    client.println("<!DOCTYPE HTML>");
}

As you can see in the sectionHeader() I want to refresh the page every 2 seconds. It works, but after 3 or 4 refreshes it hangs and I have to reset the whole board.

Of course with an embedded system I would use Ajax... here I thought reloading the page should be enough.

What might cause such a hang?

5
  • I recommend stm32duino.com
    – Juraj
    Jan 14, 2020 at 10:14
  • 1
    Welcome to the shockingly bad world of the String object. Ditch it as a first priority.
    – Majenko
    Jan 14, 2020 at 10:16
  • @Majenko, I used the String object only to parse the incoming GET request. Do you think it's worth to remove it, about my problem?
    – Mark
    Jan 14, 2020 at 15:01
  • 1. You may want to look at the HTTP conversation with Wireshark. 2. What does your server do when the client requests "GET /favicon.ico"? 3. What if it instead requests "HEAD /favicon.ico"? Jan 23, 2020 at 8:39
  • @EdgarBonet, it just doesn't answer. Is this a bad behavior? Should I provide an answer anyway?
    – Mark
    Jan 24, 2020 at 12:43

1 Answer 1

1

The code you have that says readString += c has to allocate a whole new string whenever it runs out of space for more characters. All those allocations are filling up memory.

Instead of the String class, use a single C character array, e.g.

char s[128];

that is big enough for whatever you put in it.

If it helps, I wrote a simple arduino web server for my own project, and if you look at the code here that may give you ideas for how to implement this.

1
  • Or just set readString = "" after processing the request, I guess.
    – Mark
    Jan 23, 2020 at 8:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.