esp8266 / Arduino

ESP8266 core for Arduino
GNU Lesser General Public License v2.1
15.98k stars 13.34k forks source link

Source code affecting programming!? #3547

Closed caverna closed 7 years ago

caverna commented 7 years ago

Basic Infos

The way you write source code affects the programmer, causing errors when flashing to ESP8266

Hardware

Hardware: ESP8266-01 Core Version: 2.3.0

Description

It appears to be a lie, but if I uncomment the define USE_FAIL in the sample sketch attached, I'm not able to flash the sketch anymore! I get 99% of the time the _espcomm_uploadmem failed error. Just comment the define again and miraculously you can flash 100% all the time...

Settings in IDE

Module: Generic ESP8266 Module Flash Size: 512KB/64KB CPU Frequency: 80Mhz Flash Mode: dio Flash Frequency: 40Mhz Upload Using: SERIAL Reset Method: ck

Sketch


#include <Arduino.h>

// You'll find two 'loop' and the 'define' below alternates between them
// The first one enabled can be flashed without any problem,
// but the second one affects the flashing program somehow.

//#define USE_FALTY

static const uint8_t GPIO0 = 0;
static const uint8_t GPIO1 = 1;
static const uint8_t GPIO2 = 2;
static const uint8_t GPIO3 = 3;

void setup(void) {
  pinMode(GPIO0, INPUT);
  pinMode(GPIO2, INPUT);
  pinMode(GPIO1, OUTPUT);
}

#ifndef USE_FALTY

int lastState;

void loop(void) {
  int button1 = digitalRead(GPIO0);
  int button2 = digitalRead(GPIO2);
  if (button1 == HIGH && button2 == HIGH) {
    delay(1);
    return;
  }

  if (lastState == HIGH)
    lastState = LOW;
  else
    lastState = HIGH;

  digitalWrite(GPIO1, lastState);
  while (digitalRead(GPIO0) == LOW || digitalRead(GPIO2) == LOW) {
    delay(1);
  }
}

#endif // !USE_FALTY

#ifdef USE_FALTY

void loop(void) {
  int button1 = digitalRead(GPIO0);
  int button2 = digitalRead(GPIO2);

  if (button1 == LOW)
    digitalWrite(GPIO1, HIGH);
  else if (button2 == LOW)
    digitalWrite(GPIO1, LOW);
}

#endif // USE_FALTY

Debug Messages

Uploading 'Sketch3' to 'Generic ESP8266 Module' using 'COM3'
Uploading 227088 bytes from C:\xxxxxxx/SKETCH~1.BIN to flash at 0x00000000
................................................................................ [ 36% ]
................................................................................ [ 72% ]
.............................................................warning: espcomm_send_command: didn't receive command response
warning: espcomm_send_command(FLASH_DOWNLOAD_DATA) failed
warning: espcomm_send_command: wrong direction/command: 0x01 0x03, expected 0x01 0x04
error: espcomm_upload_mem failed
caverna commented 7 years ago

Do you want to know something more crazy? If I put delay(1); at the end of falty loop, I'm able to program sometimes (I need to completly powerdown and powerup with GPIO0 in GND). And the buttons behave like expected!

caverna commented 7 years ago

Craziest thing here... I'm using a kind of "auto-reset" on pin CH_PD. If I let define USE_FALTY commented, I can use auto-reset without any problem, but the falty version is only flashed if I powerdown completly, thats for sure. Now I just discover that, If I put at least a delay(1); in loop, all my falty test codes works flawless! I didn't find anywhere that this is a requirement. Maybe the documentation should be update with that information!

caverna commented 7 years ago

I've keep testing here, and the problem is back when I try to configure serial in setup method! Just uncomment the serial.begin.

void setup(void) {
  //Serial.begin(115200);

  pinMode(GPIO0, INPUT);
  pinMode(GPIO2, INPUT);
  pinMode(GPIO1, OUTPUT);
}
devyte commented 7 years ago

Isn't gpio1 used for serial TX?

On Aug 24, 2017 11:12 PM, "Carlos Alberto Nunes" notifications@github.com wrote:

I've keep testing here, and the problem is back when I try to configure serial in setup method! Just uncomment the serial.begin.

void setup(void) { //Serial.begin(115200);

pinMode(GPIO0, INPUT); pinMode(GPIO2, INPUT); pinMode(GPIO1, OUTPUT); }

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/esp8266/Arduino/issues/3547#issuecomment-324805487, or mute the thread https://github.com/notifications/unsubscribe-auth/AQC6BqxQy8dkRzDVNZNnAMXjsvo52EQAks5sbi2lgaJpZM4PCGj- .

caverna commented 7 years ago

@devyte , sorry I just copy and paste without thinking too much (it was late in my localtime and I was too tired)... Later I'll post the complete code. When I did enable the serial, I take care of commenting all codes about GPIO1. May you please test my first code above (https://github.com/esp8266/Arduino/issues/3547#issue-252769779)?

devyte commented 7 years ago

You can't set up the serial port and also use the TX/RX pins as GPIO. Or rather, the behavior is undefined and can cause weird things.

Setting up the serial and using GPIO pins that are actually available works for me, so I don't see an issue in the libs.

On Aug 25, 2017 7:41 AM, "Carlos Alberto Nunes" notifications@github.com wrote:

@devyte https://github.com/devyte , sorry I just copy and paste without thinking too much (it was late in my localtime and I was too tired)... Later I'll post the complete code. When I did enable the serial, I take care of commenting all codes about GPIO1. May you please test my first code above (#3547 (comment) https://github.com/esp8266/Arduino/issues/3547#issue-252769779)?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/esp8266/Arduino/issues/3547#issuecomment-324883847, or mute the thread https://github.com/notifications/unsubscribe-auth/AQC6BmJFL6PtI0o0rm6Yqv6QQcHAyxT3ks5sbqTUgaJpZM4PCGj- .

caverna commented 7 years ago

@devyte please test this code with and without the define USE_FAIL:

//#define USE_FAIL

static const uint8_t GPIO0 = 0;
static const uint8_t GPIO1 = 1;
static const uint8_t GPIO2 = 2;
static const uint8_t GPIO3 = 3;

void button1Pressed(void);
void button2Pressed(void);

void setup(void) {
#ifdef USE_FAIL
  Serial.begin(115200);
#else
  pinMode(GPIO1, OUTPUT);
#endif // !USE_FAIL

  pinMode(GPIO0, INPUT);
  pinMode(GPIO2, INPUT);

  attachInterrupt(GPIO0, button1Pressed, FALLING);
  attachInterrupt(GPIO2, button2Pressed, FALLING);
}

void loop(void) {
  delay(1);
}

void button1Pressed(void) {
#ifdef USE_FAIL
  Serial.println("button1");
#else
  digitalWrite(GPIO1, HIGH);
#endif
}

void button2Pressed(void) {
#ifdef USE_FAIL
  Serial.println("button2");
#else
  digitalWrite(GPIO1, LOW);
#endif // USE_FAIL
}
caverna commented 7 years ago

Anyone, does this code above works in both situations for you?

devyte commented 7 years ago

If USE_FAIL is #defined, you try to use the Serial port from within an ISR, which is a nono.

On Aug 30, 2017 7:35 AM, "Carlos Alberto Nunes" notifications@github.com wrote:

Anyone, does this code above works in both situations for you?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/esp8266/Arduino/issues/3547#issuecomment-325951883, or mute the thread https://github.com/notifications/unsubscribe-auth/AQC6BmabkDTbwmZ6qZNLGp_4DTF59UY4ks5sdTr3gaJpZM4PCGj- .

caverna commented 7 years ago

Thank you @devyte ! So, back to my original question, how could a binary file affects the transmission!?

devyte commented 7 years ago

I'm sorry, I don't understand your question. Your original sketch/post has nothing to do with binary files.

On Aug 30, 2017 2:17 PM, "Carlos Alberto Nunes" notifications@github.com wrote:

Thank you @devyte https://github.com/devyte ! So, back to my original question, how could a binary file affects the transmission!?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/esp8266/Arduino/issues/3547#issuecomment-326059057, or mute the thread https://github.com/notifications/unsubscribe-auth/AQC6Bj3crQrB1pFRzqU1U9CQ5vzl2idWks5sdZkagaJpZM4PCGj- .

caverna commented 7 years ago

Well, when you compile the sketch, it turns into a binary file and it's send to ESP, right? In my examples, I just can supose that the only difference is the binary result got from compilation, right?

devyte commented 7 years ago

The "sending to the ESP" is not so simple as sending just a binary file. There is an updater class that, after init, writes data passed to it to the flash. How that data is passed to the class depends on your application and intent.

It has been suggested here to pass the .bin file to the ESP to store on the SPIFFS file system, then update the flash from that. You can then propagate the .bin file to other ESPs from the SPIFFS. How do you propagate it? One option is to have a webserver that receives it, and an http client that connects to another ESP's webserver to send it. Or you can use a tftp server/client. Or you can make your own protocol.

However, I suspect that what you have in mind is to update the flash, then read it back to send it to another ESPs. That requires understanding how the flash is laid out, and using the low level api for flash access.

Whatever else, the functionality you need is already present in the current core libs, and in multiple forms, so I don't see an issue here. Please continue your discussion on stackoverflow or esp8266.com, and close this.

On Aug 31, 2017 6:16 PM, "Carlos Alberto Nunes" notifications@github.com wrote:

Well, when you compile the sketch, it turns into a binary file and it's send to ESP, right? In my examples, I just can supose that the only difference is the binary result got from compilation, right?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/esp8266/Arduino/issues/3547#issuecomment-326422884, or mute the thread https://github.com/notifications/unsubscribe-auth/AQC6BuKkkTb2kxR1UsC7HXqj_fxacihLks5sdyLEgaJpZM4PCGj- .

caverna commented 7 years ago

Wait @devyte, I do admit that I don't know the inners of flashing processes... But the problem here is not what you described above. My problem is: two simple programs, one you can flash without problem, the other don't... I wouldn't believe if another guy said that to me, but it's happening. Why not keeping discussing that here, where the source code belongs?

devyte commented 7 years ago

@caverna apologies, it looks like I confused this with another issue while reading it from my phone. It's a bit hard to concentrate when you have a 2yo daughter screaming in your ear grabbing your phone and jumping up and down on your feet..... Ok, let's see if I can be more helpful.

First, use of the GPIOs and serial port work fine for me on a wemos D1 mini r2, on a nodemcu lolin v3, and on a witty cloud. It's just a matter of using the right pins, and not using the wrong ones. That means: don't use GPIO1 at all, because it's a serial port pin, and don't use any others that have special meaning. Try first with those pins that have absolutely no function at all. If those work, then your code is good. If the code doesn't work with the ones you want to use, then it's likely you can't use them, can use them only in a limited manner, or must do something special to use them. Although, in my case I was always able to flash correctly, and the issues I had were after boot.

Then, what is the serial port speed you are using? You should use at most 230Kbps. While some modules support higher, most cheap ones will silently and randomly corrupt the flash while writing, and you'll have oddball issues, including comms fail during the flash process. Try lower speeds.

Then, I see from your original description that you're using a generic ESP8266 module? If so, you need to take care of certain pins on bootup. I found this link to help me understand how the pins are supposed to be on bootup. That means that you need certain pullups/downs or even buttons (like what happens on the nodemcu module).

devyte commented 7 years ago

@caverna any progress? I am using something similar to this, just with different pins, and it works for me.

caverna commented 7 years ago

If I just use pins to turn on leds and read button (even with interrupts) I don't have any problems with the core of ESP (wdt errors). Some times the flash tool fails, but manually reseting the esp everything runs fine... If I try to replace leds by serial communication (HardwareSerial or SoftwareSerial, doesn't matter) (yes, I take care to free the TX and RX pin, just like here) the flash error occurs more often, but when it doesn't, I always get wdt errors. Everything starts to messup when I use Serial.begin(115200), because in setup, I'm able to turn on a led if I put the command before serial.begin. I tried that with 3 ESP8266-01 (AI Cloud Inside).

caverna commented 7 years ago

I did more test and I'm just making something wrong... I just realise that Serial.print() and Serial.println() makes my code fail! If I use Serial.write() I can have a button in GPIO0, a led in GPIO2 and feedback in serial! I really must be doing something wrong here...

caverna commented 7 years ago

Guys I found!!! The esptool.exe is the guilty! Using NodeMCU Programmer, I can flash without any problem AND without issues on serial! You guys may close this one...

devyte commented 7 years ago

@caverna the esptool shouldn't have any issues, unless you are using an older version. I'm glad you found a solution. Closing.