I am observing a very strange thing that I cannot understand. I am using a class constructor hack in C++ to speed up the device (P1) initialization. Normally the device would startup very quickly and do it’s thing. But ever since I started compiling the exact same code at 3 pm today all the devices seem to startup very slowly (less than 1/2 sec vs 3 seconds). So I was wondering if something has changed on the cloud firmware compiler side since 3 pm today (08/17/2015) PST. @Dave@BDub
I hope I am not crazy . The devices that have not been re-flashed are behaving normally with very quick startup. Neither the firmware code nor the hardware have changed before and after. Everything else works the same except for the startup delay.
The constructor syntax I am using in my C++ file looks like this:
ctrl::ctrl(){
init(); // initialize before the setup() is called to reduce startup time
}
ctrl::~ctrl(){}
void ctrl::init(void){
setZone(zone);
UART_Init();
/*some other initialization code*/
turnOnLED1(); // indicates that the system is initialized
}
Hmm, that does indeed seem strange! The only change recently is the rollback of the 4.9.3 compiler to the 4.8.4 compiler. We’re doing another round of tests for releasing new firmware and version targeting. I did also manually run a clean on the P1 build environment, so it’s possible there might have been some interaction with old code, but that seems less likely.
I wonder if we shouldn’t put together a minimal example demonstrating the slower startup time, and include that in our regression tests, so we can get good stats on expected startup time, and watch for any lost ground there. Any other details we should know for making a minimal test case, or do you have a minimal case by chance?
@Dave, I have listed everything I used in my initialization in the code below (more complete than above):
ctrl::ctrl(){
init(); // initialize before the setup() is called to reduce startup time
}
ctrl::~ctrl(){}
void ctrl::init(void){
I2Cs_Init();
setZone(-8); // set time zone to PST
UART_Init();
initSlave(); // slave I2C device
}
The initSlave function involved doing some simple math and then sending values to the I2C slave (twice).
I am not sure if this would help you as a test case. I have two communication protocols initialized here: Wire and Serial. The constructor is called right before setup().
Hmm, this makes me think it’s just taking a little while for the I2C devices to warm up and talk to eachother. I created a basic test example that turns on D7 while we wait for Wifi, and I’m seeing it consistently take about 0.5 seconds, here’s my code as a reference:
I know we made some I2C fixes recently, so that warm-up might be longer / safer?
This kind of code is a bit dangerous since the order of execution is undefined (different C++ modules are executed in arbitrary order.) What’s the reason you need these devices initialized so early rather than in setup()? We might be able to help find an alternative solution.
I am using the P1 as a master controller for a lighting system and upon powering up the P1 needs to convey some lighting configuration to the slave drivers. If you think about the light switch, you’d want instant on. With the class constructor hack the lighting information was conveyed rather quickly before. This was before the release of 0.4.4 so that was why I suspected something was different in the cloud compiler.
Can I use STARTUP() to declare class objects? I can’t find good documentation on this from the web.
I grouped some of the functions under a class in a separate C++ file. Even if I can call the I2C in STARTUP I would still need access to the class object, which needs to be declared first.
Thanks for the help! The new macro seems like an awesome way to leverage
The startup macro essentially wraps a constructor,. To keep it simple it’s best to limit to calling a single function. From that function you can call your other class constructors if you need to.
So expose a single global function that performs the initialization you require, and put that function call in a STARTUP() macro. It’s best to call all startups from the same module so they are initialized in strict order (top-to-bottom). Putting STARTUP() macros in different modules will lead to an arbitrary initialization sequence - there’s no way to say which C++ compilation unit is initialized first.