1

EDIT: The problem was caused by storing a pointer in the EEPROM. Thanks to @KIIV for helping out

Sorry for the enormous of wall of text, I'm trying to pare it down a bit.

I have two Arduino Megas that are misbehaving. Both boards produce identical output, so I'm certain it's not a hardware issue.

I'm trying to store user configuration data on the EEPROM and load it when the arduino boots. I have an object which contains flags for user settings like baud rates and serial port modes.

During void setup(), it fails to load the config from the EEPROM. It gets stuck looping through a few functions, even though those functions are not loops at all.(more details below)

However if I clear the EEPROM during void setup(), I can then save and load configurations later on, using menus invoked by the user during void main(). This works flawlessly. I'm calling the same load function in both cases, it just causes the arduino to shit itself if I call it during setup().

Here is a condensed version of my code:

struct UserCfg {/* config options */} 

void ConfigController::load_eeprom_cfg()
{
    Serial3.println("loading from eeprom");
    EEPROM.get(gp::config_address, UserCfg);
}

void ConfigController::write_user_config()
{
    Serial3.println("writing user config to eeprom");
    EEPROM.put(gp::config_address, UserCfg);
}

void ConfigController::apply_user_config()
{
    /* other serial ports omitted */
    Serial3.begin(UserCfg.serial_cfg_3.ser_speed, UserCfg.serial_cfg_3.ser_mode);
    Serial3.write("serial 3 up\n\r");

    // Allows users to set the admin terminal to any serial port
    Admin_Serial = UserCfg.admin_serial_port;
    Admin_Serial->write("Admin terminal up on this port\n\r");
}

/// checks and loads config at system boot
void ConfigController::startup()
{
    Serial3.begin(9600);
    Serial3.println("loading...");

    load_eeprom_cfg(); //<----- Not working when called here.

    // prevents loading non-existent config. Not robust, but it works for now.
    if (UserCfg.admin_port_str == nullptr)
    {
        Serial3.println("No valid config found. Using defaults.");
        write_default_cfg();    // puts hard coded defaults in the EEPROM.
        load_eeprom_cfg();      // works just fine when called here
    }
    Serial3.println("Applying...");

    apply_user_config(); //<----- Also not working when called here.
}

// Main code:

void setup()
{
    // erase_EEPROM() is is copied from the official arduino tutorial.
    ConfigController.erase_EEPROM();     // If I comment this line out, it breaks.
    ConfigController.startup();
    Serial3.print("startup done");
}

If I remove the call to erase_EEPROM from void setup(), the arduino gets stuck in a loop:

loading...
loading from eeprom
Applying...
serial 3 up

Those lines just repeat over and over.

However, when I call it exactly as you see above in void setup(), it works perfectly. The EEPROM is erased, the IF statement in ConfigController::startup() catches the bogus value, and writes the default config to the EEPROM. Once it's done, it reads it back from the EEPROM into the UserCfg, which is displayed in the menus. I can then save / load values to my hearts content from the menu like this:

write_user_config();
load_eeprom_cfg();
apply_user_config();

or for loading defaults:

write_default_cfg();
load_eeprom_cfg();
apply_user_config();
print_menu_prompt();  // This includes values from UserCfg, so I can confirm that changes are saved and then loaded.

I fail to see a functional difference between calling load_eeprom() during void setup(), vs calling it during void main(). It's the exact same function that put the value in the EEPROM to begin with.

Any help?

7
  • My guess it isn't looping at all, it resets whole mcu, or calling that Admin_serial->write with invalid pointer jumps somewhere near to reset vector. Definitely not good idea to call some variable exactly the same as type (=> UserCfg) – KIIV Nov 4 '19 at 21:37
  • Earlier I tried adding in a bunch of null pointer checks to Admin_Serial, like this: if(Admin_Serial == nullptr) Serial3.print("bad pointer to ser3"); No dice. If the pointer is bad, it is at least not null. – Mustard Tiger Nov 4 '19 at 21:41
  • It doesn't have to be nullptr. It can be anything – KIIV Nov 4 '19 at 21:42
  • Of course! I should add a check to see if it's equal to Serial, Serial1, Serial2, or Serial3. – Mustard Tiger Nov 4 '19 at 21:43
  • 1
    You've gotten me thinking about something. I'm storing a pointer in the EEPROM. That seems like a really bad idea. I cannot imagine there being any guarantee whatsoever that a pointer will be at the same memory address every time. Even if this is not the cause of the problem, I should probalby switch to storing an enum value, and using that to set the serial pointer when I load the settings. – Mustard Tiger Nov 4 '19 at 21:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.