ESP8266 Webserver Project

Moderator: Sprite_tm

User avatar
By Rasieel
#41576 Hello

if i change to the latest HTTPD with OTA Update over Webpage i cant compile my Project with the following messge:

Code: Select allc:/espressif/xtensa-lx106-elf/bin/../lib/gcc/xtensa-lx106-elf/5.1.0/../../../../xtensa-lx106-elf/bin/ld.exe: build/httpd.user1.out section `.text' will not fit in region `iram1_0_seg'
c:/espressif/xtensa-lx106-elf/bin/../lib/gcc/xtensa-lx106-elf/5.1.0/../../../../xtensa-lx106-elf/lib\libc.a(lib_a-mallocr.o):(.literal+0x20): undefined reference to `_sbrk_r'
c:/espressif/xtensa-lx106-elf/bin/../lib/gcc/xtensa-lx106-elf/5.1.0/../../../../xtensa-lx106-elf/lib\libc.a(lib_a-mallocr.o): In function `malloc_extend_top':
d:\Neo\esp8266-devkit\Espressif\dl\esp-newlib\build\xtensa-lx106-elf\newlib\libc\stdlib/../../../../../newlib/libc/stdlib/mallocr.c:2165: undefined reference to `_sbrk_r'
d:\Neo\esp8266-devkit\Espressif\dl\esp-newlib\build\xtensa-lx106-elf\newlib\libc\stdlib/../../../../../newlib/libc/stdlib/mallocr.c:2202: undefined reference to `_sbrk_r'
build/httpd_app.a(main.o):(.data.builtInUrls+0x34): undefined reference to `cgiRebootFirmware'
build/httpd_app.a(main.o):(.data.builtInUrls+0x70): undefined reference to `cgiReset'
c:/espressif/xtensa-lx106-elf/bin/../lib/gcc/xtensa-lx106-elf/5.1.0/../../../../xtensa-lx106-elf/lib\libc.a(lib_a-freer.o): In function `_malloc_trim_r':
d:\Neo\esp8266-devkit\Espressif\dl\esp-newlib\build\xtensa-lx106-elf\newlib\libc\stdlib/../../../../../newlib/libc/stdlib/mallocr.c:3325: undefined reference to `_sbrk_r'
d:\Neo\esp8266-devkit\Espressif\dl\esp-newlib\build\xtensa-lx106-elf\newlib\libc\stdlib/../../../../../newlib/libc/stdlib/mallocr.c:3332: undefined reference to `_sbrk_r'
d:\Neo\esp8266-devkit\Espressif\dl\esp-newlib\build\xtensa-lx106-elf\newlib\libc\stdlib/../../../../../newlib/libc/stdlib/mallocr.c:3340: undefined reference to `_sbrk_r'
collect2.exe: error: ld returned 1 exit status
make: *** [build/httpd.user1.out] Error 1


Original Code:
Code: Select all//===== Cgi that allows the firmware to be replaced via http POST
int ICACHE_FLASH_ATTR cgiUploadFirmware(HttpdConnData *connData) {
  if (connData->conn==NULL) return HTTPD_CGI_DONE; // Connection aborted. Clean up.

        if (!canOTA()) {
          errorResponse(connData, 400, flash_too_small);
          return HTTPD_CGI_DONE;
        }

  int offset = connData->post->received - connData->post->buffLen;
  if (offset == 0) {
    connData->cgiPrivData = NULL;
  } else if (connData->cgiPrivData != NULL) {
    // we have an error condition, do nothing
    return HTTPD_CGI_DONE;
  }

  // assume no error yet...
  char *err = NULL;
  int code = 400;

  // check overall size
  //os_printf("FW: %d (max %d)\n", connData->post->len, FIRMWARE_SIZE);
  if (connData->post->len > FIRMWARE_SIZE) err = "Firmware image too large";
  if (connData->post->buff == NULL || connData->requestType != HTTPD_METHOD_POST ||
      connData->post->len < 1024) err = "Invalid request";

  // check that data starts with an appropriate header
  if (err == NULL && offset == 0) err = check_header(connData->post->buff);

  // make sure we're buffering in 1024 byte chunks
  if (err == NULL && offset % 1024 != 0) {
    err = "Buffering problem";
    code = 500;
  }

  // return an error if there is one
  if (err != NULL) {
    DBG("Error %d: %s\n", code, err);
    httpdStartResponse(connData, code);
    httpdHeader(connData, "Content-Type", "text/plain");
    //httpdHeader(connData, "Content-Length", strlen(err)+2);
    httpdEndHeaders(connData);
    httpdSend(connData, err, -1);
    httpdSend(connData, "\r\n", -1);
    connData->cgiPrivData = (void *)1;
    return HTTPD_CGI_DONE;
  }

  // let's see which partition we need to flash and what flash address that puts us at
  uint8 id = system_upgrade_userbin_check();
  int address = id == 1 ? 4*1024                   // either start after 4KB boot partition
      : 4*1024 + FIRMWARE_SIZE + 16*1024 + 4*1024; // 4KB boot, fw1, 16KB user param, 4KB reserved
  address += offset;

  // erase next flash block if necessary
  if (address % SPI_FLASH_SEC_SIZE == 0){
    DBG("Flashing 0x%05x (id=%d)\n", address, 2 - id);
    spi_flash_erase_sector(address/SPI_FLASH_SEC_SIZE);
  }

  // Write the data
  //DBG("Writing %d bytes at 0x%05x (%d of %d)\n", connData->post->buffSize, address,
  //      connData->post->received, connData->post->len);
  spi_flash_write(address, (uint32 *)connData->post->buff, connData->post->buffLen);

  if (connData->post->received == connData->post->len){
    httpdStartResponse(connData, 200);
    httpdEndHeaders(connData);
    return HTTPD_CGI_DONE;
  } else {
    return HTTPD_CGI_MORE;
  }
}


Replaced Code from the HTTPD Framework (with Wegpage to Flash):

Code: Select all#define PAGELEN 64

#define FLST_START 0
#define FLST_WRITE 1
#define FLST_SKIP 2
#define FLST_DONE 3
#define FLST_ERROR 4

#define FILETYPE_ESPFS 0
#define FILETYPE_FLASH 1
#define FILETYPE_OTA 2
typedef struct {
   int state;
   int filetype;
   int flashPos;
   char pageData[PAGELEN];
   int pagePos;
   int address;
   int len;
   int skip;
   char *err;
} UploadState;

typedef struct __attribute__((packed)) {
   char magic[4];
   char tag[28];
   int32_t len1;
   int32_t len2;
} OtaHeader;


int ICACHE_FLASH_ATTR cgiUploadFirmware(HttpdConnData *connData) {
   CgiUploadFlashDef *def=(CgiUploadFlashDef*)connData->cgiArg;
   UploadState *state=(UploadState *)connData->cgiData;
   int len;
   char buff[128];

   if (connData->conn==NULL) {
      //Connection aborted. Clean up.
      if (state!=NULL) free(state);
      return HTTPD_CGI_DONE;
   }

   if (state==NULL) {
      //First call. Allocate and initialize state variable.
      DBG("Firmware upload cgi start.\n");
      state=malloc(sizeof(UploadState));
      if (state==NULL) {
         DBG("Can't allocate firmware upload struct!\n");
         return HTTPD_CGI_DONE;
      }
      memset(state, 0, sizeof(UploadState));
      state->state=FLST_START;
      connData->cgiData=state;
      state->err="Premature end";
   }


   char *data=connData->post->buff;
   int dataLen=connData->post->buffLen;

   while (dataLen!=0) {
      if (state->state==FLST_START) {
         //First call. Assume the header of whatever we're uploading already is in the POST buffer.
         if (def->type==CGIFLASH_TYPE_FW && memcmp(data, "EHUG", 4)==0) {
            //Type is combined flash1/flash2 file
            OtaHeader *h=(OtaHeader*)data;
            strncpy(buff, h->tag, 27);
            buff[27]=0;
            if (strcmp(buff, def->tagName)!=0) {
               DBG("OTA tag mismatch! Current=`%s` uploaded=`%s`.\n",
                              def->tagName, buff);
               len=httpdFindArg(connData->getArgs, "force", buff, sizeof(buff));
               if (len!=-1 && atoi(buff)) {
                  DBG("Forcing firmware flash.\n");
               } else {
                  state->err="Firmware not intended for this device!\n";
                  state->state=FLST_ERROR;
               }
            }
            if (state->state!=FLST_ERROR && connData->post->len > def->fwSize*2+sizeof(OtaHeader)) {
               state->err="Firmware image too large";
               state->state=FLST_ERROR;
            }
            if (state->state!=FLST_ERROR) {
               //Flash header seems okay.
               dataLen-=sizeof(OtaHeader); //skip header when parsing data
               data+=sizeof(OtaHeader);
               if (system_upgrade_userbin_check()==1) {
                  DBG("Flashing user1.bin from ota image\n");
                  state->len=h->len1;
                  state->skip=h->len2;
                  state->state=FLST_WRITE;
                  state->address=def->fw1Pos;
               } else {
                  DBG("Flashing user2.bin from ota image\n");
                  state->len=h->len2;
                  state->skip=h->len1;
                  state->state=FLST_SKIP;
                  state->address=def->fw2Pos;
               }
            }
         } else if (def->type==CGIFLASH_TYPE_FW && checkBinHeader(connData->post->buff)) {
            if (connData->post->len > def->fwSize) {
               state->err="Firmware image too large";
               state->state=FLST_ERROR;
            } else {
               state->len=connData->post->len;
               state->address=def->fw1Pos;
               state->state=FLST_WRITE;
            }
         } else if (def->type==CGIFLASH_TYPE_ESPFS && checkEspfsHeader(connData->post->buff)) {
            if (connData->post->len > def->fwSize) {
               state->err="Firmware image too large";
               state->state=FLST_ERROR;
            } else {
               state->len=connData->post->len;
               state->address=def->fw1Pos;
               state->state=FLST_WRITE;
            }
         } else {
            state->err="Invalid flash image type!";
            state->state=FLST_ERROR;
            DBG("Did not recognize flash image type!\n");
         }
      } else if (state->state==FLST_SKIP) {
         //Skip bytes without doing anything with them
         if (state->skip>dataLen) {
            //Skip entire buffer
            state->skip-=dataLen;
            dataLen=0;
         } else {
            //Only skip part of buffer
            dataLen-=state->skip;
            data+=state->skip;
            state->skip=0;
            if (state->len) state->state=FLST_WRITE; else state->state=FLST_DONE;
         }
      } else if (state->state==FLST_WRITE) {
         //Copy bytes to page buffer, and if page buffer is full, flash the data.
         //First, calculate the amount of bytes we need to finish the page buffer.
         int lenLeft=PAGELEN-state->pagePos;
         if (state->len<lenLeft) lenLeft=state->len; //last buffer can be a cut-off one
         //See if we need to write the page.
         if (dataLen<lenLeft) {
            //Page isn't done yet. Copy data to buffer and exit.
            memcpy(&state->pageData[state->pagePos], data, dataLen);
            state->pagePos+=dataLen;
            state->len-=dataLen;
            dataLen=0;
         } else {
            //Finish page; take data we need from post buffer
            memcpy(&state->pageData[state->pagePos], data, lenLeft);
            data+=lenLeft;
            dataLen-=lenLeft;
            state->pagePos+=lenLeft;
            state->len-=lenLeft;
            //Erase sector, if needed
            if ((state->address&(SPI_FLASH_SEC_SIZE-1))==0) {
               spi_flash_erase_sector(state->address/SPI_FLASH_SEC_SIZE);
            }
            //Write page
            DBG("Writing %d bytes of data to SPI pos 0x%x...\n", state->pagePos, state->address);
            spi_flash_write(state->address, (uint32 *)state->pageData, state->pagePos);
            state->address+=PAGELEN;
            state->pagePos=0;
            if (state->len==0) {
               //Done.
               if (state->skip) state->state=FLST_SKIP; else state->state=FLST_DONE;
            }
         }
      } else if (state->state==FLST_DONE) {
         DBG("Huh? %d bogus bytes received after data received.\n", dataLen);
         //Ignore those bytes.
         dataLen=0;
      } else if (state->state==FLST_ERROR) {
         //Just eat up any bytes we receive.
         dataLen=0;
      }
   }
   
   if (connData->post->len==connData->post->received) {
      //We're done! Format a response.
      DBG("Upload done. Sending response.\n");
      httpdStartResponse(connData, state->state==FLST_ERROR?400:200);
      httpdHeader(connData, "Content-Type", "text/plain");
      httpdEndHeaders(connData);
      if (state->state!=FLST_DONE) {
         httpdSend(connData, "Firmware image error:", -1);
         httpdSend(connData, state->err, -1);
         httpdSend(connData, "\n", -1);
      }
      free(state);
      return HTTPD_CGI_DONE;
   }

   return HTTPD_CGI_MORE;
}
User avatar
By Sprite_tm
#41977 I have no idea what you're doing there. Some of the errors you refer to are because the code somehow links to newlibs malloc() instead of os_malloc(). Some errors I can't explain, like the cgiReset etc not being found. I have also no idea what the last two bits of code you post are. Care to explain the problem any further?