stm32duino / STM32Ethernet

Arduino library to support Ethernet for STM32 based board
151 stars 42 forks source link

Question about WebServerFreeRTOS Example #67

Closed s1lvi0 closed 1 year ago

s1lvi0 commented 1 year ago

Hi, I'm trying to use the STM32Ethernet library to create a web server but I'm having problems when using it with FreeRTOS. I crashed FreeRTOS after trying several times to refresh a simple html page. Specifically I modified the example to use a char array as the html page and then write to the client, the page works fine for a few times but when I stress test it with 10-15 browser tabs, and 1 second auto refresh after 1-5 minutes the problem happen. Sometimes the green led will quickly flash four times, other times it will stop without saying anything. The four blink I think are related to this function in FreeRTOS :

/** Hard fault - blink four short flash every two seconds */
void HardFault_Handler() {
  errorBlink(4);
}

Is this normal behavior with this type of use or did I do something wrong?

This is the actual test code:

/*
  Port of WebServer on FreeRTOS

  A simple web server that shows the value of the analog input pins.
  2 task are created:
    Ethernet: to manage the server
    Analog to read input values

  Circuit:
   STM32 board with Ethernet support
   Analog inputs attached to pins A0 through A5 (optional)

  created 18 Dec 2009
  by David A. Mellis
  modified 9 Apr 2012
  by Tom Igoe
  modified 02 Sept 2015
  by Arturo Guadalupi
  modified 23 Jun 2017
  by Wi6Labs
  modified 1 Jun 2018
  by sstaub
*/

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

// Enter an IP address for your controller below.
// The IP address will be dependent on your local network:
IPAddress ip(192, 168, 10, 15);

// Initialize the Ethernet server library
// with the IP address and port you want to use
// (port 80 is default for HTTP):
EthernetServer server(80);

#define ANALOG_CHANEL_NUMBER 6
int sensorReading[ANALOG_CHANEL_NUMBER];

const char page[] = R"=====(

                                <!DOCTYPE html>
                                <html>
                                <head>
                                <title>Test Page</title>
                                </head>
                                <body>

                                <h1>Lorem Ipsum</h1>

                                <p>
                                Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum dignissim mi dui, a cursus diam feugiat sed. Vivamus condimentum tellus eget ante pellentesque congue. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse felis ligula, vulputate non congue et, faucibus et est. Sed at egestas risus. Vivamus id feugiat sem. Maecenas quam ligula, condimentum in pulvinar ut, tempor et tellus. Fusce vestibulum urna consectetur ligula tincidunt, eget efficitur leo porttitor. Vestibulum ac tincidunt lacus. Pellentesque convallis, purus sed fermentum fermentum, erat ipsum laoreet ante, id congue erat nisi et sem. Praesent molestie nisi vitae arcu rutrum, in gravida augue ultrices. Sed ultrices enim ac aliquet consequat. Vestibulum a lacus id ante placerat vehicula ut et ante. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.

Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Fusce lacinia id quam at tempus. Morbi ut dignissim dolor. Nunc aliquet scelerisque ligula molestie sollicitudin. Cras mollis lacinia nisi nec efficitur. Mauris elementum magna vitae lectus tristique venenatis. Praesent massa arcu, dictum non eros non, placerat blandit ligula. Aenean dignissim magna mi, interdum suscipit turpis facilisis quis. Mauris nibh libero, pretium id neque et, pellentesque viverra nisi. Nullam dapibus purus eu odio posuere, vitae hendrerit orci dapibus. Nam nisl orci, scelerisque vitae luctus at, fringilla eu turpis. Quisque id diam eget tellus lacinia volutpat quis sed odio. Fusce diam massa, ultrices ut gravida eu, fermentum ut tortor.

Ut eleifend sem in risus ultrices, sit amet aliquet metus vulputate. Duis imperdiet in nisi non luctus. Donec metus leo, eleifend in accumsan id, iaculis nec massa. In lacus urna, faucibus non lobortis nec, feugiat non nisi. Aliquam vel nisl quis elit sodales egestas in sit amet urna. Sed dolor neque, rhoncus et mi at, tempor malesuada odio. Suspendisse non nulla id tortor commodo fringilla. In pretium metus porta placerat fringilla. Sed viverra imperdiet massa sit amet consectetur. Praesent bibendum mauris in facilisis cursus. Pellentesque luctus convallis feugiat. Sed sit amet nisi vel ligula pharetra eleifend. Nam vel commodo dolor, mattis sollicitudin eros. Mauris gravida, velit id feugiat sodales, nisi nulla fringilla metus, sed efficitur nibh ipsum eu nunc.

Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Cras laoreet odio eu fringilla convallis. Maecenas ac lorem eu sapien fermentum semper. Nulla faucibus orci non sem fermentum, ut semper turpis mattis. Vestibulum auctor vitae libero in imperdiet. Quisque nec nibh in arcu fermentum placerat. Cras interdum dictum congue. Mauris pretium efficitur tortor, sed sollicitudin metus venenatis nec. Curabitur sit amet nibh hendrerit, laoreet augue vel, placerat risus.

Ut pretium lorem enim. Sed aliquam vestibulum erat, vitae lacinia elit dapibus sit amet. Vestibulum malesuada est in imperdiet ultrices. Duis feugiat augue condimentum justo auctor cursus. Nunc fringilla nisi non quam vulputate, ut fringilla lacus commodo. Quisque non neque quis leo feugiat aliquet. Fusce non facilisis mauris. Morbi condimentum erat a massa luctus commodo. Vivamus ultricies lorem sit amet lacus molestie, a volutpat sapien maximus.
                                </p>

                                </body>
                                </html>

                                )=====";

void taskAnalog(void* arg) {
  UNUSED(arg);
  while (1) {
    for (int analogChannel = 0; analogChannel < ANALOG_CHANEL_NUMBER; analogChannel++) {
      sensorReading[analogChannel] = analogRead(analogChannel);
    }
    Serial.println("Task 2");
    vTaskDelay(1000); // read Analog every seconds
  }
}

// task code
void taskETH(void* arg) {
  UNUSED(arg);
  // start the Ethernet connection and the server:
  Ethernet.begin(ip);
  server.begin();
  Serial.print("server is at ");
  Serial.println(Ethernet.localIP());

  while (1) {
    // listen for incoming clients
    EthernetClient client = server.available();
    if (client) {
      Serial.println("new client");
      // an http request ends with a blank line
      bool currentLineIsBlank = true;
      while (client.connected()) {
        if (client.available()) {
          char c = client.read();
          Serial.write(c);
          // if you've gotten to the end of the line (received a newline
          // character) and the line is blank, the http request has ended,
          // so you can send a reply
          if (c == '\n' && currentLineIsBlank) {
            // send a standard http response header
            client.println("HTTP/1.1 200 OK");
            client.println("Content-Type: text/html");
            client.println("Connection: close"); // the connection will be closed after completion of the response
            client.println("Refresh: 1");        // refresh the page automatically every 5 sec
            client.println();

            client.write(page);
            break;
          }
          if (c == '\n') {
            // you're starting a new line
            currentLineIsBlank = true;
          } else if (c != '\r') {
            // you've gotten a character on the current line
            currentLineIsBlank = false;
          }
        }
      }
      // give the web browser time to receive the data
      delay(1);
      // close the connection:
      client.stop();
      Serial.println("client disconnected");
    }
  }
}

void setup() {
  // Open serial communications and wait for port to open:
  Serial.begin(115200);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }
  Serial.println("START");

  portBASE_TYPE s = xTaskCreate(taskETH, NULL, 900, NULL, 1, NULL);
  if (s != pdPASS) {
    printf("Ethernet task creation failed\n");
    while (1);
  }

  s = xTaskCreate(taskAnalog, NULL, 200, NULL, 2, NULL);
  if (s != pdPASS) {
    printf("Analog task creation failed\n");
    while (1);
  }

  vTaskStartScheduler();
  Serial.println("Scheduler failed");
  while (1);
}

void loop() {
  // Not used.
}
fpistm commented 1 year ago

Hi, which board? Maybe linked to interrupt priority or RAM ? FreeRTOS is provided "as is", several customization can be required.

s1lvi0 commented 1 year ago

Sorry, the board is a NUCLEO-F767ZI.

FreeRTOS is provided "as is", several customization can be required.

Can you point me on which type of costumization, like heap management or configs for rtos. Thanks

image

fpistm commented 1 year ago

Nucleo F767ZI has 512kb of RAM so it should not be the issue. For customization you can have a look to this: https://github.com/stm32duino/STM32FreeRTOS#configuration

I will not have time to test this, I advise to try to get some help on the forum.

fpistm commented 1 year ago

Hi @s1lvi0 Could you retry with the latest STM32FreeRTOS version we fixed an issue linked to Ethernet priority.