if i change to the latest HTTPD with OTA Update over Webpage i cant compile my Project with the following messge:
c:/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:
//===== 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):
#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;
}