SpenceKonde/ReleaseScripts

The "NVM_STATUS 'was not declared in this scope" error is still present when compiling on Linux.

Closed this issue · 20 comments

When using Arduino on Linux, the error "'NVM_STATUS' was not declared in this scope" still occurs when trying to compile a program that uses macro "eeprom_busy_wait()" from <avr/eeprom.h>. The problem does not occur with the same file compiled under Windows. Both have "megaTinyCore" version 2.5.10 installed.

Is that a manual installation megaTinyCore there, and board manager on windows? You need either a board manager installation or manual compiler toolchain update to not receive that error (the defect is in the toolchain - board manager install will update it to the version specified by the board manager json - for this core, that's a version which is about 18 months ahead of the most recent one Arduino ships. (and I am oh so glad I didn't wait for an official arduino toolchain version)

On both systems megaTinyCore was installed by the board manager. In both cases Arduino itself is installed in the "portable" version from the unpacked archive.

Please enable verbose compilation in preferences and get me the full output. If you can't get it to attach to github, put it into a tarball and email it to spencekonde@gmail.com.

There is something different about your configuration, as we have enough linux users that it is implausible that none of them use eeprom.

[Warning] Output path is not specified. Unable to reuse previously compiled files. Build will be slower. See README.
Picked up JAVA_TOOL_OPTIONS: 
Loading configuration...
Initializing packages...
Preparing boards...
Verifying...
/home/mpro/work/arduino/arduino-builder -dump-prefs -logger=machine -hardware /home/mpro/work/arduino/hardware -hardware /home/mpro/work/arduino/portable/packages -tools /home/mpro/work/arduino/tools-builder -tools /home/mpro/work/arduino/hardware/tools/avr -tools /home/mpro/work/arduino/portable/packages -built-in-libraries /home/mpro/work/arduino/libraries -libraries /home/mpro/work/arduino/portable/sketchbook/libraries -fqbn=megaTinyCore:megaavr:atxy4:chip=1614,clock=20internal,bodvoltage=2v6,bodmode=disabled,eesave=enable,millis=enabled,startuptime=8,wiremode=mors,printf=default,attach=allenabled -ide-version=10819 -build-path /tmp/arduino_build_120049 -warnings=none -build-cache /tmp/arduino_cache_990403 -prefs=build.warn_data_percentage=75 -prefs=runtime.tools.arduinoOTA.path=/home/mpro/work/arduino/portable/packages/arduino/tools/arduinoOTA/1.3.0 -prefs=runtime.tools.arduinoOTA-1.3.0.path=/home/mpro/work/arduino/portable/packages/arduino/tools/arduinoOTA/1.3.0 -prefs=runtime.tools.avr-gcc.path=/home/mpro/work/arduino/portable/packages/DxCore/tools/avr-gcc/7.3.0-atmel3.6.1-azduino4b -prefs=runtime.tools.avr-gcc-7.3.0-atmel3.6.1-azduino4b.path=/home/mpro/work/arduino/portable/packages/DxCore/tools/avr-gcc/7.3.0-atmel3.6.1-azduino4b -prefs=runtime.tools.python3.path=/home/mpro/work/arduino/portable/packages/megaTinyCore/tools/python3/3.7.2-post1 -prefs=runtime.tools.python3-3.7.2-post1.path=/home/mpro/work/arduino/portable/packages/megaTinyCore/tools/python3/3.7.2-post1 -prefs=runtime.tools.avrdude.path=/home/mpro/work/arduino/portable/packages/DxCore/tools/avrdude/6.3.0-arduino17or18 -prefs=runtime.tools.avrdude-6.3.0-arduino17or18.path=/home/mpro/work/arduino/portable/packages/DxCore/tools/avrdude/6.3.0-arduino17or18 -verbose /home/mpro/work/arduino/portable/sketchbook/Test/test.ino
/home/mpro/work/arduino/arduino-builder -compile -logger=machine -hardware /home/mpro/work/arduino/hardware -hardware /home/mpro/work/arduino/portable/packages -tools /home/mpro/work/arduino/tools-builder -tools /home/mpro/work/arduino/hardware/tools/avr -tools /home/mpro/work/arduino/portable/packages -built-in-libraries /home/mpro/work/arduino/libraries -libraries /home/mpro/work/arduino/portable/sketchbook/libraries -fqbn=megaTinyCore:megaavr:atxy4:chip=1614,clock=20internal,bodvoltage=2v6,bodmode=disabled,eesave=enable,millis=enabled,startuptime=8,wiremode=mors,printf=default,attach=allenabled -ide-version=10819 -build-path /tmp/arduino_build_120049 -warnings=none -build-cache /tmp/arduino_cache_990403 -prefs=build.warn_data_percentage=75 -prefs=runtime.tools.arduinoOTA.path=/home/mpro/work/arduino/portable/packages/arduino/tools/arduinoOTA/1.3.0 -prefs=runtime.tools.arduinoOTA-1.3.0.path=/home/mpro/work/arduino/portable/packages/arduino/tools/arduinoOTA/1.3.0 -prefs=runtime.tools.avr-gcc.path=/home/mpro/work/arduino/portable/packages/DxCore/tools/avr-gcc/7.3.0-atmel3.6.1-azduino4b -prefs=runtime.tools.avr-gcc-7.3.0-atmel3.6.1-azduino4b.path=/home/mpro/work/arduino/portable/packages/DxCore/tools/avr-gcc/7.3.0-atmel3.6.1-azduino4b -prefs=runtime.tools.python3.path=/home/mpro/work/arduino/portable/packages/megaTinyCore/tools/python3/3.7.2-post1 -prefs=runtime.tools.python3-3.7.2-post1.path=/home/mpro/work/arduino/portable/packages/megaTinyCore/tools/python3/3.7.2-post1 -prefs=runtime.tools.avrdude.path=/home/mpro/work/arduino/portable/packages/DxCore/tools/avrdude/6.3.0-arduino17or18 -prefs=runtime.tools.avrdude-6.3.0-arduino17or18.path=/home/mpro/work/arduino/portable/packages/DxCore/tools/avrdude/6.3.0-arduino17or18 -verbose /home/mpro/work/arduino/portable/sketchbook/Test/test.ino
Using board 'atxy4' from platform in folder: /home/mpro/work/arduino/portable/packages/megaTinyCore/hardware/megaavr/2.5.10
Using core 'megatinycore' from platform in folder: /home/mpro/work/arduino/portable/packages/megaTinyCore/hardware/megaavr/2.5.10
Detecting libraries used...
/home/mpro/work/arduino/portable/packages/DxCore/tools/avr-gcc/7.3.0-atmel3.6.1-azduino4b/bin/avr-g++ -c -g -Os -Wall -std=gnu++17 -fpermissive -Wno-sized-deallocation -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -Wno-error=narrowing -flto -mrelax -w -x c++ -E -CC -mmcu=attiny1614 -DF_CPU=20000000L -DCLOCK_SOURCE=0 -DTWI_MORS -DMILLIS_USE_TIMERD0 -DCORE_ATTACH_ALL -DARDUINO=10819 -DARDUINO_AVR_ATtiny1614 -DARDUINO_ARCH_MEGAAVR "-DMEGATINYCORE=\"2.5.9\"" -DMEGATINYCORE_MAJOR=2UL -DMEGATINYCORE_MINOR=5UL -DMEGATINYCORE_PATCH=9UL -DMEGATINYCORE_RELEASED=1 -DARDUINO_attinyxy4 -I/home/mpro/work/arduino/portable/packages/megaTinyCore/hardware/megaavr/2.5.10/cores/megatinycore/api/deprecated -I/home/mpro/work/arduino/portable/packages/megaTinyCore/hardware/megaavr/2.5.10/cores/megatinycore -I/home/mpro/work/arduino/portable/packages/megaTinyCore/hardware/megaavr/2.5.10/variants/txy4 /tmp/arduino_build_120049/sketch/test.ino.cpp -o /dev/null
Generating function prototypes...
/home/mpro/work/arduino/portable/packages/DxCore/tools/avr-gcc/7.3.0-atmel3.6.1-azduino4b/bin/avr-g++ -c -g -Os -Wall -std=gnu++17 -fpermissive -Wno-sized-deallocation -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -Wno-error=narrowing -flto -mrelax -w -x c++ -E -CC -mmcu=attiny1614 -DF_CPU=20000000L -DCLOCK_SOURCE=0 -DTWI_MORS -DMILLIS_USE_TIMERD0 -DCORE_ATTACH_ALL -DARDUINO=10819 -DARDUINO_AVR_ATtiny1614 -DARDUINO_ARCH_MEGAAVR "-DMEGATINYCORE=\"2.5.9\"" -DMEGATINYCORE_MAJOR=2UL -DMEGATINYCORE_MINOR=5UL -DMEGATINYCORE_PATCH=9UL -DMEGATINYCORE_RELEASED=1 -DARDUINO_attinyxy4 -I/home/mpro/work/arduino/portable/packages/megaTinyCore/hardware/megaavr/2.5.10/cores/megatinycore/api/deprecated -I/home/mpro/work/arduino/portable/packages/megaTinyCore/hardware/megaavr/2.5.10/cores/megatinycore -I/home/mpro/work/arduino/portable/packages/megaTinyCore/hardware/megaavr/2.5.10/variants/txy4 /tmp/arduino_build_120049/sketch/test.ino.cpp -o /tmp/arduino_build_120049/preproc/ctags_target_for_gcc_minus_e.cpp
/home/mpro/work/arduino/tools-builder/ctags/5.8-arduino11/ctags -u --language-force=c++ -f - --c++-kinds=svpf --fields=KSTtzns --line-directives /tmp/arduino_build_120049/preproc/ctags_target_for_gcc_minus_e.cpp
Compiling sketch...
/home/mpro/work/arduino/portable/packages/DxCore/tools/avr-gcc/7.3.0-atmel3.6.1-azduino4b/bin/avr-g++ -c -g -Os -Wall -std=gnu++17 -fpermissive -Wno-sized-deallocation -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -Wno-error=narrowing -MMD -flto -mrelax -mmcu=attiny1614 -DF_CPU=20000000L -DCLOCK_SOURCE=0 -DTWI_MORS -DMILLIS_USE_TIMERD0 -DCORE_ATTACH_ALL -DARDUINO=10819 -DARDUINO_AVR_ATtiny1614 -DARDUINO_ARCH_MEGAAVR "-DMEGATINYCORE=\"2.5.9\"" -DMEGATINYCORE_MAJOR=2UL -DMEGATINYCORE_MINOR=5UL -DMEGATINYCORE_PATCH=9UL -DMEGATINYCORE_RELEASED=1 -DARDUINO_attinyxy4 -I/home/mpro/work/arduino/portable/packages/megaTinyCore/hardware/megaavr/2.5.10/cores/megatinycore/api/deprecated -I/home/mpro/work/arduino/portable/packages/megaTinyCore/hardware/megaavr/2.5.10/cores/megatinycore -I/home/mpro/work/arduino/portable/packages/megaTinyCore/hardware/megaavr/2.5.10/variants/txy4 /tmp/arduino_build_120049/sketch/test.ino.cpp -o /tmp/arduino_build_120049/sketch/test.ino.cpp.o
In file included from /home/mpro/work/arduino/portable/packages/DxCore/tools/avr-gcc/7.3.0-atmel3.6.1-azduino4b/avr/include/avr/io.h:99:0,
                 from /home/mpro/work/arduino/portable/packages/megaTinyCore/hardware/megaavr/2.5.10/cores/megatinycore/core_devices.h:8,
                 from /home/mpro/work/arduino/portable/packages/megaTinyCore/hardware/megaavr/2.5.10/cores/megatinycore/Arduino.h:22,
                 from /tmp/arduino_build_120049/sketch/test.ino.cpp:1:
/home/mpro/work/arduino/portable/sketchbook/Test/test.ino: In function 'void setup()':
test:35:5: error: 'NVM_STATUS' was not declared in this scope
     eeprom_busy_wait();
     ^
/home/mpro/work/arduino/portable/sketchbook/Test/test.ino:35:5: note: suggested alternative: 'AC2_STATUS'
test:35:5: error: 'NVM_NVMBUSY_bp' was not declared in this scope
     eeprom_busy_wait();
     ^
/home/mpro/work/arduino/portable/sketchbook/Test/test.ino:35:5: note: suggested alternative: 'NVMCTRL_FBUSY_bp'
exit status 1
IntelliSense configuration already up to date. To manually rebuild your IntelliSense configuration run "Ctrl+Alt+I"
[Error] Verifying sketch 'test.ino': Exit with code=1

I see "-DARDUINO_ARCH_MEGAAVR "-DMEGATINYCORE="2.5.9"" in log but in board manager i have this

That's expected. 2.5.9 was released in a panic, and I forgot to bump the version number, not related to the issue at hand.

Can you post the contents of your sketch? I'm trying to reconcile the contents of the toolchain files and the errors you got, it does not make sense for that message to be showing up based on what I have thus seen. .

#include <Arduino.h>
#include <avr/eeprom.h>

uint8_t ebyte {100};

void setup()
{
    eeprom_update_byte((uint8_t *)&ebyte, 0x00);
    eeprom_busy_wait();
}

void loop()
{
}

You're saying that compiles for windows? I get the same sort of error.

But t<avr/eeprom.h> is not within my sphere of responsibility to maintain. That's microchip's job, and they aren't particularly diligent about it.

That's why the EEPROM.h library included with the core (providing the usual Arduino EEPROM.h interface) doesn't actually use avr/eeprom.h, I'd forgotten we still have zero usage of t symbols from avr/eeprom,h.... (I'd thought it was fixed, but I must have been mistaken, it's still broken in all versions of the toolchain I have around.)

The megaTinyCore/DxCore cores use the same EEPROM.h with the following for read and write;

The assembly was partly based on the avr-libc code (I used it as a sanity check), but I wasn't happy with how it's interactions with millis were not particularly graceful nor the fact that there was a 1 clock window during which an interrupt that used NVMCTRL could shit on a pending write and corrupt the eeprom (not that it's smart to write to NVM in an ISR except in extreme circumstances).

// Access/read members.
  uint8_t operator * () const            {
    return (*(uint8_t *)((uint16_t)(MAPPED_EEPROM_START + (index & EEPROM_INDEX_MASK))));
  }

  EERef &operator = (uint8_t in)       {
    #ifdef MEGATINYCORE
    // I see no reason why eeprom_write_byte() won't corrupt EEPROM if an ISR tries to write at the wrong instant. The window is 1 clock, but not 0
    uint16_t adr = (uint16_t)MAPPED_EEPROM_START + (index & EEPROM_INDEX_MASK);
    __asm__ __volatile__(
      "ldi r30, 0x00"     "\n\t" // point the Z register at NVMCTRL.
      "ldi r31, 0x10"     "\n\t"
      "in r0, 0x3f"       "\n\t" // read the SREG into r0 to narrow the window between sbrc and cli.
      "ldd r18, Z+2"      "\n\t" // read NVMCTRL.STATUS into r18
      "andi r18, 3"       "\n\t" // if NVMCTRL is busy....
      "brne .-6"          "\n\t" // repeat until it's not.
      "cli"               "\n\t" // disable interrupts. 3 clock window during which an interrupt couldstart write since we checked
      //                            but this just means millis will lose time - nvmctrl halts CPU to finish last write
      "st X, %0"          "\n\t" // write the value we were passed
      "ldi %0, 0x9D"      "\n\t" // CCP signature loaded in it's place
      "out 0x34, %0"      "\n\t" // protection enabled
      "ldi %0, 0x03"      "\n\t" // command loaded: page erase-write.
      "st Z, %0"          "\n\t" // write the page erase-write command to nvmctrl.ctrla
      "out 0x3f, r0"      "\n"   // restore SREG
      :"+d"(in)           // take the value we are writing in any upper register as read/write,
      : "x"(adr)          // and the address (not the index) in X
      : "r30", "r31", "r18");      // clobber Z and r18. We needed an upper register for the temporary value to andi it. I wonder if this will fix the eeprom bugs too?
    return *this;
    #else
    uint8_t oldSREG = SREG;
    while (NVMCTRL.STATUS & NVMCTRL_EEBUSY_bm);
    // check at start - not end. Makes writing single bytes fasterms
    // Note that we only have interrupts disabled for the dozen or so clock cycles
    // during which we *start* the write, not for the while loop, and we save SREG
    // before the while loop. That way there is only a 1 clock window where an
    // interrupt that starts a write will cause this write to halt the CPU
    // which would cause millis() to lose time.
    // Note that writing more than 1 byte in an ISR will **always** cause millis to lose time.
    cli();

    _PROTECTED_WRITE_SPM(NVMCTRL.CTRLA, NVMCTRL_CMD_NONE_gc);
    _PROTECTED_WRITE_SPM(NVMCTRL.CTRLA, NVMCTRL_CMD_EEERWR_gc);
    *(uint8_t *)(MAPPED_EEPROM_START + (index & EEPROM_INDEX_MASK)) = in;

    SREG = oldSREG; // restore SREG and interrupts
    return *this;
    #endif
  }

The equivalent of eeprom_busy_wait() is

    while (NVMCTRL.STATUS & NVMCTRL_EEBUSY_bm);

Yes, the code builds without problems on Windows (on two different Win10 and Win11 machines). I know <avr/eeprom.h> is not yours, but I find it strange that it works on Windows and not on Linux: /. I need the functions from <avr/eeprom.h> for my bootloader and I just need to do a workaround to redefine the macro "eeprom_busy_wait ()"

I think I found the source of the problem, ... on windows in the eeprom.h file I have:

#if defined (__DOXYGEN__)
# define eeprom_is_ready ()
#elif defined (NVM_STATUS)
# define eeprom_is_ready () bit_is_clear (NVM_STATUS, NVM_NVMBUSY_bp)
#elif defined (NVMCTRL_STATUS)
# define eeprom_is_ready () bit_is_clear (NVMCTRL_STATUS, NVMCTRL_EEBUSY_bp)
#elif defined (DEECR)
# define eeprom_is_ready () bit_is_clear (DEECR, BSY)
#elif defined (EEPE)
# define eeprom_is_ready () bit_is_clear (EECR, EEPE)
#else
# define eeprom_is_ready () bit_is_clear (EECR, EEWE)
#endif

and that's ok, and on linux it's:

#if defined (__DOXYGEN__)
# define eeprom_is_ready ()
#elif defined (__AVR_XMEGA__) && __AVR_XMEGA__
# define eeprom_is_ready () bit_is_clear (NVM_STATUS, NVM_NVMBUSY_bp)
#elif defined (DEECR)
# define eeprom_is_ready () bit_is_clear (DEECR, BSY)
#elif defined (EEPE)
# define eeprom_is_ready () bit_is_clear (EECR, EEPE)
#else
# define eeprom_is_ready () bit_is_clear (EECR, EEWE)
#endif

old version causing the problem.

Do you prepare packages separately for each system?

Yeah, I have to prepare them separately for windows vs everything else - otherwise the line endings are fucked and nothing works.

The method used to prepare them is horrifying since I most certainly do not know how to set up a build environment that can cross-compile the toolchain for or what, 7 platforms? the Azduino packages are frankenstein'ed together from the last Arduino package and the last

A build is run on a linux system in the cloud specifying the latest ATmega, ATtiny, and Dx-series ATpacks, on a rather large linux system (to get the build time down to something sane - it's an EC2 compute instance with like 8 threads or something, would cost a fortune to keep deployed). That generates an x64 linux version and all the pre-compiled shit. That is downloaded and then the cloud system is shut down.
That gets extracted to windows, alongside the last Arduino toolchain. All the includes and precompiled AVR .a and .o files are copied onto the Arduino package, replacing what was there (but leaving the last arduino package's working binary tools in place)
The same archives (newly build x64 linux, and all the arduino7 packages for non-windows platforms) are copied to WSL ubuntu.
A series of commands is copy+pasted from text files to copy the files and and repack them .
The wndows archive is copied to the same location in wsl, and another command is copied and pasted from a text file, and the output passed through a regex also copy-pasted from a text file, to transform it into the information that is needed for the board manager json, except for the URL for x64 linux being wrong, because 95+% of the traffic for that is from github actions CI. The other platforms are uploaded to Amazon S3 manually. The x64 linux version is uploaded to the github repo so that I don't go broke and so github doesn't waste tons of bandwith to outside their network. Finally, the x64 linux version is uploaded to github, the final URL added to board manager json, and the board manager json file updated.

You can see why I only do this when there's a compelling update. It's been quite a while (I think the last time was to pick up the 322x support, and the next will likely be when the AVR64DD28 and AVR64DD32 parts show up on Microchip Direct as available to preorder.

something must have been done differently when I ran the azduino4b round (which was only done for windows, because I'd screwed up somewhere and created a bad package)

This isssue is a low priority as it does not impact users of any features supplied by the core. The last toolchain package was released 9 months ago (Microchip hasn't released any substantive improvements to the ATpacks since then, except some things related to the DD series, which they still aren't shipping...) and you're the first one to notice...

But the most important thing is that you already know what and how to fix it :)

Yeah - making sure it's fixed in Azduino5 won't be a problem.

Moving over here - this repo is a closer match for the nature of the issue.

Gaaaah! That's what's going on! Instead this issue has spread to all platforms.

Okay, that's two more files that need to be deleted before the copy when preparing a new package. (power.h and eeprom.h suffered regressions).

Azduino7b will correct this issue.

this is fixed in latest releases