SpenceKonde / megaTinyCore

Arduino core for the tinyAVR 0/1/2-series - Ones's digit 2,4,5,7 (pincount, 8,14,20,24), tens digit 0, 1, or 2 (featureset), preceded by flash in kb. Library maintainers: porting help available!
Other
551 stars 142 forks source link

Serial.begin(): Error compiling for ATtiny204 #252

Closed nlCortana closed 3 years ago

nlCortana commented 3 years ago

Hi,

I get an error when compiling Serial.begin(9600) for the ATtiny204.

When I switch chip to ATtiny404 it works fine. Results in 57% flash size. So I think Arduino Serial Library is to large to fit my ATtiny204 device. This is my first Tiny 1-series experience. Is there a workaround like a lightweight Serial library, or should I order the ATtiny1604 :)

Kind regards!

Here is verbose output:

C:\Program Files (x86)\Arduino\arduino-builder -dump-prefs -logger=machine -hardware C:\Program Files (x86)\Arduino\hardware -hardware C:\Users\AlJo\AppData\Local\Arduino15\packages -tools C:\Program Files (x86)\Arduino\tools-builder -tools C:\Program Files (x86)\Arduino\hardware\tools\avr -tools C:\Users\AlJo\AppData\Local\Arduino15\packages -built-in-libraries C:\Program Files (x86)\Arduino\libraries -libraries C:\Users\AlJo\Documents\Arduino\libraries -fqbn=megaTinyCore:megaavr:atxy4:serialevent=no,chip=204,clock=20internal,bodvoltage=1v8,bodmode=disabled,eesave=enable,millis=enabled,resetpin=UPDI,startuptime=8,uartvoltage=5v -vid-pid=1A86_7523 -ide-version=10812 -build-path C:\Users\AlJo\AppData\Local\Temp\arduino_build_382508 -warnings=none -build-cache C:\Users\AlJo\AppData\Local\Temp\arduino_cache_613026 -prefs=build.warn_data_percentage=75 -prefs=runtime.tools.avr-gcc.path=C:\Users\AlJo\AppData\Local\Arduino15\packages\arduino\tools\avr-gcc\7.3.0-atmel3.6.1-arduino7 -prefs=runtime.tools.avr-gcc-7.3.0-atmel3.6.1-arduino7.path=C:\Users\AlJo\AppData\Local\Arduino15\packages\arduino\tools\avr-gcc\7.3.0-atmel3.6.1-arduino7 -prefs=runtime.tools.arduinoOTA.path=C:\Users\AlJo\AppData\Local\Arduino15\packages\arduino\tools\arduinoOTA\1.3.0 -prefs=runtime.tools.arduinoOTA-1.3.0.path=C:\Users\AlJo\AppData\Local\Arduino15\packages\arduino\tools\arduinoOTA\1.3.0 -prefs=runtime.tools.avrdude.path=C:\Users\AlJo\AppData\Local\Arduino15\packages\arduino\tools\avrdude\6.3.0-arduino17 -prefs=runtime.tools.avrdude-6.3.0-arduino17.path=C:\Users\AlJo\AppData\Local\Arduino15\packages\arduino\tools\avrdude\6.3.0-arduino17 -verbose C:\Users\AlJo\Documents\Arduino\t204_switch\t204_switch.ino C:\Program Files (x86)\Arduino\arduino-builder -compile -logger=machine -hardware C:\Program Files (x86)\Arduino\hardware -hardware C:\Users\AlJo\AppData\Local\Arduino15\packages -tools C:\Program Files (x86)\Arduino\tools-builder -tools C:\Program Files (x86)\Arduino\hardware\tools\avr -tools C:\Users\AlJo\AppData\Local\Arduino15\packages -built-in-libraries C:\Program Files (x86)\Arduino\libraries -libraries C:\Users\AlJo\Documents\Arduino\libraries -fqbn=megaTinyCore:megaavr:atxy4:serialevent=no,chip=204,clock=20internal,bodvoltage=1v8,bodmode=disabled,eesave=enable,millis=enabled,resetpin=UPDI,startuptime=8,uartvoltage=5v -vid-pid=1A86_7523 -ide-version=10812 -build-path C:\Users\AlJo\AppData\Local\Temp\arduino_build_382508 -warnings=none -build-cache C:\Users\AlJo\AppData\Local\Temp\arduino_cache_613026 -prefs=build.warn_data_percentage=75 -prefs=runtime.tools.avr-gcc.path=C:\Users\AlJo\AppData\Local\Arduino15\packages\arduino\tools\avr-gcc\7.3.0-atmel3.6.1-arduino7 -prefs=runtime.tools.avr-gcc-7.3.0-atmel3.6.1-arduino7.path=C:\Users\AlJo\AppData\Local\Arduino15\packages\arduino\tools\avr-gcc\7.3.0-atmel3.6.1-arduino7 -prefs=runtime.tools.arduinoOTA.path=C:\Users\AlJo\AppData\Local\Arduino15\packages\arduino\tools\arduinoOTA\1.3.0 -prefs=runtime.tools.arduinoOTA-1.3.0.path=C:\Users\AlJo\AppData\Local\Arduino15\packages\arduino\tools\arduinoOTA\1.3.0 -prefs=runtime.tools.avrdude.path=C:\Users\AlJo\AppData\Local\Arduino15\packages\arduino\tools\avrdude\6.3.0-arduino17 -prefs=runtime.tools.avrdude-6.3.0-arduino17.path=C:\Users\AlJo\AppData\Local\Arduino15\packages\arduino\tools\avrdude\6.3.0-arduino17 -verbose C:\Users\AlJo\Documents\Arduino\t204_switch\t204_switch.ino Using board 'atxy4' from platform in folder: C:\Users\AlJo\AppData\Local\Arduino15\packages\megaTinyCore\hardware\megaavr\2.1.3 Using core 'megatinycore' from platform in folder: C:\Users\AlJo\AppData\Local\Arduino15\packages\megaTinyCore\hardware\megaavr\2.1.3 Detecting libraries used... "C:\Users\AlJo\AppData\Local\Arduino15\packages\arduino\tools\avr-gcc\7.3.0-atmel3.6.1-arduino7/bin/avr-g++" -c -g -Os -w -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -Wno-error=narrowing -flto -w -x c++ -E -CC -mmcu=attiny204 -DF_CPU=20000000L -DARDUINO=10812 -DARDUINO_ATtiny204 -DARDUINO_ARCH_MEGAAVR -DNOSERIALEVENT -DMILLIS_USE_TIMERA0 -DUARTBAUD5V "-IC:\Users\AlJo\AppData\Local\Arduino15\packages\megaTinyCore\hardware\megaavr\2.1.3\cores\megatinycore/api/deprecated" "-IC:\Users\AlJo\AppData\Local\Arduino15\packages\megaTinyCore\hardware\megaavr\2.1.3\cores\megatinycore" "-IC:\Users\AlJo\AppData\Local\Arduino15\packages\megaTinyCore\hardware\megaavr\2.1.3\variants\txy4" "C:\Users\AlJo\AppData\Local\Temp\arduino_build_382508\sketch\t204_switch.ino.cpp" -o nul Generating function prototypes... "C:\Users\AlJo\AppData\Local\Arduino15\packages\arduino\tools\avr-gcc\7.3.0-atmel3.6.1-arduino7/bin/avr-g++" -c -g -Os -w -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -Wno-error=narrowing -flto -w -x c++ -E -CC -mmcu=attiny204 -DF_CPU=20000000L -DARDUINO=10812 -DARDUINO_ATtiny204 -DARDUINO_ARCH_MEGAAVR -DNOSERIALEVENT -DMILLIS_USE_TIMERA0 -DUARTBAUD5V "-IC:\Users\AlJo\AppData\Local\Arduino15\packages\megaTinyCore\hardware\megaavr\2.1.3\cores\megatinycore/api/deprecated" "-IC:\Users\AlJo\AppData\Local\Arduino15\packages\megaTinyCore\hardware\megaavr\2.1.3\cores\megatinycore" "-IC:\Users\AlJo\AppData\Local\Arduino15\packages\megaTinyCore\hardware\megaavr\2.1.3\variants\txy4" "C:\Users\AlJo\AppData\Local\Temp\arduino_build_382508\sketch\t204_switch.ino.cpp" -o "C:\Users\AlJo\AppData\Local\Temp\arduino_build_382508\preproc\ctags_target_for_gcc_minus_e.cpp" "C:\Program Files (x86)\Arduino\tools-builder\ctags\5.8-arduino11/ctags" -u --language-force=c++ -f - --c++-kinds=svpf --fields=KSTtzns --line-directives "C:\Users\AlJo\AppData\Local\Temp\arduino_build_382508\preproc\ctags_target_for_gcc_minus_e.cpp" Compiling sketch... "C:\Users\AlJo\AppData\Local\Arduino15\packages\arduino\tools\avr-gcc\7.3.0-atmel3.6.1-arduino7/bin/avr-g++" -c -g -Os -w -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -Wno-error=narrowing -MMD -flto -mmcu=attiny204 -DF_CPU=20000000L -DCLOCK_SOURCE=0 -DARDUINO=10812 -DARDUINO_ATtiny204 -DARDUINO_ARCH_MEGAAVR -DNOSERIALEVENT -DMILLIS_USE_TIMERA0 -DUARTBAUD5V "-IC:\Users\AlJo\AppData\Local\Arduino15\packages\megaTinyCore\hardware\megaavr\2.1.3\cores\megatinycore/api/deprecated" "-IC:\Users\AlJo\AppData\Local\Arduino15\packages\megaTinyCore\hardware\megaavr\2.1.3\cores\megatinycore" "-IC:\Users\AlJo\AppData\Local\Arduino15\packages\megaTinyCore\hardware\megaavr\2.1.3\variants\txy4" "C:\Users\AlJo\AppData\Local\Temp\arduino_build_382508\sketch\t204_switch.ino.cpp" -o "C:\Users\AlJo\AppData\Local\Temp\arduino_build_382508\sketch\t204_switch.ino.cpp.o" Compiling libraries... Compiling core... Using precompiled core: C:\Users\AlJo\AppData\Local\Temp\arduino_cache_613026\core\core_bfda876a8c654f33002d0129adf8f99a.a Linking everything together... "C:\Users\AlJo\AppData\Local\Arduino15\packages\arduino\tools\avr-gcc\7.3.0-atmel3.6.1-arduino7/bin/avr-gcc" -w -Os -g -flto -fuse-linker-plugin -Wl,--gc-sections -Wl,--section-start=.text=0x0 -mmcu=attiny204 -o "C:\Users\AlJo\AppData\Local\Temp\arduino_build_382508/t204_switch.ino.elf" "C:\Users\AlJo\AppData\Local\Temp\arduino_build_382508\sketch\t204_switch.ino.cpp.o" "C:\Users\AlJo\AppData\Local\Temp\arduino_build_382508/..\arduino_cache_613026\core\core_bfda876a8c654f33002d0129adf8f99a.a" "-LC:\Users\AlJo\AppData\Local\Temp\arduino_build_382508" -lm c:/users/aljo/appdata/local/arduino15/packages/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino7/bin/../lib/gcc/avr/7.3.0/../../../../avr/bin/ld.exe: address 0x8ec of C:\Users\AlJo\AppData\Local\Temp\arduino_build_382508/t204_switch.ino.elf section '.text' is not within region 'text'

c:/users/aljo/appdata/local/arduino15/packages/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino7/bin/../lib/gcc/avr/7.3.0/../../../../avr/bin/ld.exe: C:\Users\AlJo\AppData\Local\Temp\arduino_build_382508/t204_switch.ino.elf section '.rodata' will not fit in region 'text

c:/users/aljo/appdata/local/arduino15/packages/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino7/bin/../lib/gcc/avr/7.3.0/../../../../avr/bin/ld.exe: address 0x8ec of C:\Users\AlJo\AppData\Local\Temp\arduino_build_382508/t204_switch.ino.elf section '.text' is not within region 'text'

c:/users/aljo/appdata/local/arduino15/packages/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino7/bin/../lib/gcc/avr/7.3.0/../../../../avr/bin/ld.exe: region `text' overflowed by 310 bytes

collect2.exe: error: ld returned 1 exit status

exit status 1 Error compiling for board ATtiny1614/1604/814/804/414/404/214/204.

SpenceKonde commented 3 years ago

Well, I daresay it isn't your first tiny 1-series experience, seeing as that part isn't 1-series, it's 0-series! I mean, if you're stepping up to a 1604, you might as well go for the 1614, which for an extra few cents, will give you a DAC, twice as much RAM, and a few other goodies..... It's such a nice part that it's my "go to" AVR these days...

Trying to do anything in Arduino-land with 2k parts is painful - making a compatible implementation of Serial is always going to be kind of bulky, but the stock implementation for hardware serial for the modern AVR parts seems to be particularly bad (there's other buried treasure in there that really ought to be fixed)... I've looked at the generated assembly, and a surprising amount of that goes to the pair of ISRs, which look to be terribly inefficient. I'm sure it could be done better; at this point, it's so lousy there are non-trivial performance implications.... But a more compact implementation of Serial is not even close to a priority for me right now... I don't know that anyone else has made any attempt at it either. It doesn't look like much thought was given to the compile size of Serial when it was written (this version was copied from the official core for the Uno WiFi Rev. 2 and Nano Every, which use the same peripherals)

SpenceKonde commented 3 years ago

Oh - and 2.1.4 will save you a non-trivial amount of flash, actually - while I was in there adding a little feature, I found a couple of bugs, and next thing I knew, I'd made substantial changes, and had it saving a significant amount of flash on low-flash parts (it drops the OSCERR sigrow correction to internal oscillator-derived baud rates, since it's accurate enough for UART to work when talking to a serial adapter anyway); larger flash parts don't save as much - I ripped out all the interrupt priority adjusting madness and just made the poll function ALSO look at the interrupt status and also manually call the ISR if there's another interrupt running; saves a fair amount of flash, and there was really no good that could come of unnecessarily fiddling with interrupt priority (especially not when the next thing you're doing is POLLING THE DAMNED INTERRUPT FLAG).....

SpenceKonde commented 3 years ago

Just found a way to save more flash in the process of figuring out how I managed to break alternate pins....

You may actually be able to fit it with 2.1.4 (being released shortly)....

There is still room to save more flash by reimplementing the DRE ISR (I'm sure there's a classic rap lyric by Dr. Dre just begging to be turned into a joke here :-P ), which I think could be done significantly more efficiently. I suspect it would need to be hand-written assembly though, and it's just not worth it, especially since it only really hurts once you have multiple serial ports AND are using them; in that case, there's a pointless ~50b tax per serial port because the entire prologue and epilogue is present in each ISR, but only two instructions are different between them; they're both ldi's so you would still need two push'es to make room in the working registers for them, but the rest of the dozen push and pop instructions could be put into the common isr implementation used for all serial ports, by making the isr's naked and doing all that stuff by hand... this looks like a job foooor.... someone else! And like I said, it ain't really worth it - on the parts with a billion serial ports, there's also oodles of flash.

SpenceKonde commented 3 years ago

Yeah, you might get away with it on the 204 in 2.1.4 @nlCortana

I just compared the bare minimum of something using Serial for output on a 14-pin 0-series tiny, and went from 2073 bytes to 1693! 380 bytes of savings, and you were only 310b over...

SpenceKonde commented 3 years ago

Though some of that savings came from eliminating a reference to digitalWrite in begin(), so if you're using analogWrite() (which calls digitalWrite() if you pass a duty cycle of 0 or 255) or digitalWrite() anywhere, you won't see the whole savings.... Though with these changes, you may well be close enough that you can get rid of calls to the those functions yourself and squeak by... Assuming you know you're in striking distance, it is a great exercise and will make you a better embedded systems programmer.

nlCortana commented 3 years ago

Wow, after your first comment I did not think you would comeback to this issue anytime soon. So I ordered some ATtiny1614 like you mentioned, and they arrived today. I even ordered a few ATtiny1607 Curiosity Nano Evaluation Kit with it to test the onboard UPDI debugger in MPLAB or AVR studio (and perhaps Arduino).

I'm not very well taught yet on whats going on insight a 'core' for Arduino. From what I now it is an extensive set of wrappers to get the Arduino (wiring) library working again for a different microcontroller (like register mappings) So some of your explanation is not fully clear to me.

I started working with the AT90S2313 back in 2004 when Elektor Magazine released a development board for it. Used to program it in BASCOM. Later I started coding my own interfaces for communicating with GSM modem's, and GPS in C. Now as a teacher I feel devoted to interest young students with small accessible embedded systems.

I will let you know if 2.1.4 will work for me. Thanks for your amazing effort updating MegaTinyCore

Regards

SpenceKonde commented 3 years ago

Well, you can still make use of the '204's in your original project, I suspect, and put the '1614's to use on some other project. Those 1614's are just amazing parts... 14 pins (with 12 I/O pins, 11 of which are readily usable) really is a sweet spot - 8 pins only gets you 5 real I/O's, which just isn't enough for very many use cases, while the 20+ pincount packages are either godawful to solder (VQFN) or gargantuan (SOIC-20), and the price difference between the tiny-flash 204 and 16k flash 2k ram 1614 is pretty small. Never did understand why Atmel never used the SOIC-16 package instead of SOIC-14... it's the same narrow width (and similarly cheap to manufacture) as the SOIC-14, but you get 2 more pins....

Your understanding of a "core" is exactly right! It implements the Arduino API calls (things like digitalWrite, for example), as well as a couple of key classes, most notably the HardwareSerial class (which is presented to the user in the form of Serial). It also includes architecture/part specific libraries (like Wire and SPI, and sometimes others; my cores, for example, contain my modified version of the AdafruitNeoPixel library called tinyNeoPixel, which has significantly lower flash usage, particularly if you use the Static version, which trades some little-used functionality and 1:1 compatible constructor syntax for 1.something k of flash.

You might be surprised to learn that things like digitalWrite and pinMode are incredibly bulky and slow, especially when for compiletime known arguments, it can optimize down to 2 bytes and 1 processor clock cycle (2 on classic AVRs - CBI/SBI execute in a single clock cycle instead of 2 on the new parts). For compile-time-known cases (ex, pinMode(1,INPUT), as opposed to pinMode(variable-pin-number,INPUT) the compiler is able to optimize them pretty well on "modern" (ie,. post-2016) AVRs, but on classic parts, they're just as slow and inefficient with constant pins, largely because of the effort involved in translating the arduino pin number back to the port and bit within that port - the fact that the array is in PROGMEM stymies the optimizer. IIRC on a classic atmega328p, it;s like 100 bytes or something of overhead... ). In the case of Serial.begin() (where it sets a pin as output), because there are two sets of pins it could use, it doesnt get to do that optimization, or not nearly as much as it otherwise could.... But there was previously an unnecessary call to digitalWrite() in there too (not only was it, at best, unnececessary, at worst it could produce surprising behavior when reusing the pin after calling Serial.end(); if that was the only call to digitalWrite() anywhere in the sketch, removing that would save considerably more flash, as the whole digitalWrite() function would no longer be needed - but if you use digitalWrite() with a non-constant pin elsewhere, losing that digitalWrite() call would only save a few bytes (though the other changes I made would still add up to significant savings).

Personally I despise the official development kits. Then again, you probably would too if you literally had a bin full of development boards you designed (inventory for my Tindie store)... I can't stand MPLAB, or the official programmers, either (tried to use MPLAB and a pair of SNAP programmers I got a while back. Never managed to make them work!)... I also don't like debuggers (not for embedded development, and not for desktop software - it always seems to take more effort troubleshooting the debugging tools and learning to work with them than they save me. There are occasions when I do see the value of them, but they're few and far between, compared to things that can be expediently handled with more primitive debugging methods.

In all honesty, though I love what Microchip has done with the AVR architecture since buying Atmel (kicked up the features several notches while cutting the prices by a factor of ~5), I can't say they leave me with a great impression sometimes. Their development tools are horrendous to work with IME (thank god for Arduino), my interactions with their support folks have been.... less than inspiring (unless you count coming up new insults), their testing - at best - has some pretty serious qualitative blind spots (I really do have faith in their quantitative testing.... but there are a lot of things that obviously got essentially zero testing. At my day job, I do software test, and one thing they drill into us, is that they never want a customer to say "Didn't you even try it?" and have to admit that they hadn't - and like half of the entries on the (lengthy) list of errata for the new AVR DA and DB-series parts fall into that category....