1

This compiles fine (Arduino):

struct ProgressStore {
  unsigned long ProgressStart; 
  unsigned long LastStored;    
  uint32_t FirstSectorNr;      
};

void IRAM_ATTR ProgressInit(ProgressStore aProgressStore){
}

Leave out the IRAM_ATTR and it doesn't compile anymore(?):

Verbruiksmeter:116:6: error: variable or field 'ProgressInit' declared void
  116 | void ProgressInit(ProgressStore aProgressStore){//, uint32_t SectorNr) {
      |      ^~~~~~~~~~~~
Verbruiksmeter:116:19: error: 'ProgressStore' was not declared in this scope
  116 | void ProgressInit(ProgressStore aProgressStore){//, uint32_t SectorNr) {
 

 |                   ^~~~~~~~~~~~~
Bigman74066
  • 408
  • 4
  • 12
  • Leaving out IRAM_ATTR AND the function argument also makes it compile... – Bigman74066 Dec 02 '21 at 13:50
  • Arduino does this mean thing where it find all of your function definitions, and generates a function declaration above the rest of your code. The result is that you're trying to use ProgressStore before the ProgressStore struct is declared. I believe the IRAM_ATTR must suppress this behavior. – JohnFilleau Dec 02 '21 at 13:52
  • Please edit your question to contain [mcve], otherwise we can only guess. – Slava Dec 02 '21 at 13:52
  • So, you showed code that works, and asked about something else? Post the code that **doesn't work**. – Pete Becker Dec 02 '21 at 14:00
  • 1
    Thank you Pete, that's very helpful... – Bigman74066 Dec 03 '21 at 19:06

1 Answers1

5

See here: https://stackoverflow.com/a/17493585/2027196

Arduino does this mean thing where it finds all of your function definitions in main, and generates a function declaration for each above the rest of your code. The result is that you're trying to use ProgressStore before the ProgressStore struct is declared. I believe the IRAM_ATTR must suppress this behavior.

It ends up generating this before compilation:

void ProgressInit(ProgressStore aProgressStore); // <-- ProgressStore not yet declared

struct ProgressStore {
  unsigned long ProgressStart; //Value of the counter at the start of the sector
  unsigned long LastStored;    //Should be new CounterValue-1, but you never know...
  uint32_t FirstSectorNr;      //1st of 2 sectors used for storage of progress
};

void ProgressInit(ProgressStore aProgressStore) {//, uint32_t SectorNr) {
//  ProgressStore.1stSector = SectorNr;
}

One solution is to move your structures and classes into their own .h files, and include those at the top.

ProgressStore.h

#ifndef PROGRESS_STORE_H
#define PROGRESS_STORE_H

struct ProgressStore {
  unsigned long ProgressStart; //Value of the counter at the start of the sector
  unsigned long LastStored;    //Should be new CounterValue-1, but you never know...
  uint32_t FirstSectorNr;      //1st of 2 sectors used for storage of progress
};

#endif // PROGRESS_STORE_H

main.cpp

#include "ProgressStore.h"

void ProgressInit(ProgressStore aProgressStore) {//, uint32_t SectorNr) {
//  ProgressStore.1stSector = SectorNr;
}

The function declaration is still auto-generated, but inserted after your #includes

JohnFilleau
  • 4,045
  • 1
  • 15
  • 22
  • Thank you for this exellent explanation. I was busting my head on this one... this did the trick. I simply moved the struct declaration to the top of the file. – Bigman74066 Dec 02 '21 at 14:04
  • It's really one of the most frustrating Arduino "features" from the point of view of someone wanting the transition from Arduino to "real" C++ to be easier. – JohnFilleau Dec 02 '21 at 14:13
  • I remember the good old days where I could do everything with Turbo Pascal and later Delphi. *sigh* – Bigman74066 Dec 02 '21 at 14:17
  • 1
    You can also change your code to `void ProgressInit(struct ProgressStore aProgressStore)` which forward declares `ProgressStore` so you don't need a separate header – Artyer Dec 02 '21 at 14:53
  • @Artyer presumably the function is going to want to access members of the struct, and it will need the full definition for that. All you're doing is changing the type and location of the error. – Mark Ransom Dec 02 '21 at 19:06
  • @Artyer the question shows the error generated on the function definition, not the declaration. – Mark Ransom Dec 02 '21 at 19:26
  • @MarkRansom This is because the arduino preprocessor uses line directives. The error is actually in the definition in the intermediary ".ino.cpp" file, but it shows the source in the ".ino" file – Artyer Dec 02 '21 at 19:36