Reading multiple analog pins fails to compile
aspyra opened this issue · comments
I am trying to update an old program to the new 2.0.0 version.
Calling 'analogRead(A3)' by itself compiles, but trying to read analog channels 1-3:
'analogRead(A1); analogRead(A2); analogRead(A3);'
Fails to compile, throwing badArg("Analog pin must be a constant");
Tried to find the root of the problem, but I cannot find __builtin_constant_p() function anywhere.
Can you post your code so I can have a look?
Thanks for reporting BTW, it was easy enough to reproduce:
{
}
void loop()
{
analogRead(A1);
analogRead(A2);
analogRead(A3);
// It does compile if the line above is commented out
}
In function 'check_valid_analog_pin',
inlined from 'analogRead' at /Users/hans/Documents/Arduino/hardware/MicroCore/avr/cores/microcore/wiring_analog.c:27:3:
/Users/hans/Documents/Arduino/hardware/MicroCore/avr/cores/microcore/Arduino.h:147:7: error: call to 'badArg' declared with attribute error:
badArg("Analog pin must be a constant");
^
lto-wrapper: fatal error: /Applications/Arduino.app/Contents/Java/hardware/tools/avr/bin/avr-gcc returned 1 exit status
compilation terminated.
/Applications/Arduino.app/Contents/Java/hardware/tools/avr/bin/../lib/gcc/avr/7.3.0/../../../../avr/bin/ld: error: lto-wrapper failed
collect2: error: ld returned 1 exit status
exit status 1
Error compiling for board ATtiny13.
@nerdralph do you have any idea why this is happening? The code is borrowed from picoCore.
I have looked through the code and the fuction check_valid_analog_pin(analog_pin_t pin) is already using this atribute. Adding it to AnalogRead() allows the code to be compiled. I guess the question now is, what's better: dropping/restating the check or inlining all calls to analogRead().
Adding __attribute__((always_inline))
increases the compiled size quite a lot if it's used multiple times in the project. Maybe it's best to remove the check_valid_analog_pin(pin)
check? The analogRead()
function already requires an argument that is analog_pin_t
, so we pretty much have a valid check already, since analogRead(0)
won't compile.
I just did some comparisons between picoCore and MicroCore. For a basic sketch, adding a call to analogRead increases the sketch size by 46 bytes for MicroCore, vs 18 bytes for picoCore. picoCore uses always_inline, and each additional call to analogRead() takes 20 more bytes. If I remove the always_inline, and rely on the analog pin enum for ensuring a valid analog pin, the second analogRead() call takes 18 more bytes, and every subsequent takes 6 more.
Since MicroCore's analogRead is much larger, it makes sense not to inline it. I think I'll even drop the always_inline in picoCore since it can save a few extra bytes.
I also confirmed that you can call analogRead(0) in a .c file, but I don't think this is a big concern as anyone creating multi-file sketches with extern "C" functions should be smart enough to know better.
adding a call to analogRead increases the sketch size by 46 bytes for MicroCore, vs 18 bytes for picoCore
How can this be? I'm looking at the source code for analogRead, and they are identical, except that MicroCore sets the ADC prescaler based on F_CPU
@nerdralph I tried to compile similar sketches for MicroCore and picoCore. It turns out that analogRead increases the sketch size with MicroCore with 20 bytes. It's also 20 bytes with picoCore (on my computer, avr-gcc 7.3.0), but you do have some other neat tricks to reduce the size of a blank sketch that I haven't been able to figure out.
I've just pushed a fix for this issue, where I just remove the pin constant check. I'll release MicroCore 2.0.1 very soon
A new release, v2.0.1 is now available, where I've just removed the check_valid_analog_pin
check.