Teensy 4.0 - section attribute not allowed

Status
Not open for further replies.

webline

Member
I'm using atom/platformio to compile my code. My program complies without an error for the Teensy 3.2 oder 3.6. Now I switched to set the Teensy 4.0 as my target and get those compile errors:

Code:
include/RotaryEncoder.h:24:42: error: section attribute not allowed for 'TURN_CNT'
const PROGMEM int TURN_CNT         = 4;   // Zahl der Impulse je Schritt

include/RotaryEncoder.h:25:42: error: section attribute not allowed for 'PRELL_PRESSED_MS'
const PROGMEM int PRELL_PRESSED_MS = 500; // Entprellen
 
In file included from src/TeensyDisplay.cpp:4:0:
include/TeensyDisplay.h:25:38: error: section attribute not allowed for 'DEF_FONT'
const PROGMEM int DEF_FONT     = 0;

include/TeensyDisplay.h:26:38: error: section attribute not allowed for 'FONT_HEIGHT'
const PROGMEM int FONT_HEIGHT  = 8;

...

Compiling .pio/build/teensy40/FrameworkArduino/DMAChannel.cpp.o
Compiling .pio/build/teensy40/FrameworkArduino/EventResponder.cpp.o
Compiling .pio/build/teensy40/FrameworkArduino/HardwareSerial.cpp.o
In file included from src/main.cpp:25:0:
include/TeensyDisplay.h:25:38: error: section attribute not allowed for 'DEF_FONT'
const PROGMEM int DEF_FONT     = 0;

Seems to be related to the const attribute but I don't understand the problem - any hint how to fix it would be nice.

Thanks!
 
I refer to Pauls statement:

To force a function or array into flash only, use PROGMEM.
To force code into TCM (which is currently the default), use FASTRUN. When/if that alternate linker script is published (or if you hack one yourself), you'll want to have FASTRUN on your interrupts and other speed sensitive code.


There is plenty of RAM too so I don't need to use PROGMEM - but do I have to change the code here for T4.0? Sorry - but I still don't understand the difference to the T3.x

I would use

#ifdef TEENSY40

to get the individual code for the Teensy 4.0

Thanks!!!
 
Last edited:
Currently your program can either have PROGMEM on code OR data, but not both, as this will currently give you a linker error.

As for your errors above, hard to know what is going on, without seeing the rest of the code.

That is, I had a test sketch that included:
Code:
uint8_t dtcm_array[10];
uint8_t DMAMEM ocram_array[10];
const uint8_t const_array[] = "ABCD";
uint8_t const_progmem_array[] PROGMEM = "XYZ";
const PROGMEM int FONT_HEIGHT  = 8;
And it compiles fine on Arduino 1.8.9 with current released Teensyduino...

I have seen something similar to that error is for example I put the defines in some other source file, like: foo.c
And foo.c did not include any of the header files necessary to properly define things like PROGMEM.
 
The affected parts of the code:

first .h file
Code:
      const PROGMEM int CLK_PIN          = 18;  // CLK
      const PROGMEM int DT_PIN           = 19;  // DT
      const PROGMEM int SW_PIN           = 17;  // SW
      const PROGMEM int TURN_CNT         = 4;   // Zahl der Impulse je Schritt
      const PROGMEM int PRELL_PRESSED_MS = 500; // Entprellen

2nd .h file
Code:
      static PROGMEM const int PIN_RESET = 15;
      static PROGMEM const int PIN_DC    = 5;
      static PROGMEM const int PIN_CS    = 10;
      static PROGMEM const int PIN_SCK   = 13;
      static PROGMEM const int PIN_MOSI  = 11;

      const PROGMEM int DEF_FONT     = 0;
      const PROGMEM int FONT_HEIGHT  = 8;
      const PROGMEM int FONT_V_SPACE = 1;

main.cpp

Code:
     const PROGMEM menuItem_t MENU_ITEMS[NUMBER_OF_MENU_ITEMS] = {
      // id, label, action, menuLevel, newLevel, aTarget
      { 0, "Zu Ebene 2", MENU_MENU,   0 , 1 ,  NONE_ACTION},
      { 1, "Zu Ebene 3", MENU_MENU,   0 , 2 ,  NONE_ACTION},
      { 2, "Menu L1 C",  MENU_ACTION, 0 , -1 , FIRS_ACTION},
      { 3, "Menu L1 D",  MENU_ACTION, 0 , -1 , SCND_ACTION},

      { 4, "Zu Ebene 3", MENU_MENU,   1 , 2 ,  NONE_ACTION},
      { 5, "Menu L2 B",  MENU_ACTION, 1 , -1 , THRD_ACTION},
      { 6, "Back",       MENU_BACK,   1 , 0 ,  NONE_ACTION},

      { 7, "Menu L3 A",  MENU_ACTION, 2 , -1 , FOUR_ACTION},
      { 8, "Menu L3 B",  MENU_ACTION, 2 , -1 , FIVE_ACTION},
      { 9, "Menu L3 C",  MENU_ACTION, 2 , -1 , SIXT_ACTION},
      {10, "Menu L3 D",  MENU_ACTION, 2 , -1 , SIXT_ACTION},
      {11, "Back",       MENU_BACK,   2 , 1 ,  NONE_ACTION},
    };

    const PROGMEM menuStructure_t MENU_STRUCTURE[NUMBER_OF_MENU_LEVEL] = {
      // LEVEL, ITEMS
      { 0, 4 },
      { 1, 3 },
      { 2, 5 },
    };

compiles for teensy 3.2 and 3.6 - I now solved it with

Code:
#ifdef TEENSY40
and removed PROGMEM for Teensy 4.0

P.S.: I do have this too in my code:

Code:
class MainMenu {
private:
  static PROGMEM const int NUMBER_OF_MENU_ITEMS = 12; // wie viele Menue-Eintraege gibt es insgesamt
  static PROGMEM const int NUMBER_OF_MENU_LEVEL = 3;  // wie viele Menue-Level gibt es

never got an error by the compiler for that?!
 
Last edited:
I'm using atom/platformio to compile my code. My program complies without an error for the Teensy 3.2 oder 3.6. Now I switched to set the Teensy 4.0 as my target and get those compile errors:

Code:
include/RotaryEncoder.h:24:42: error: section attribute not allowed for 'TURN_CNT'
const PROGMEM int TURN_CNT         = 4;   // Zahl der Impulse je Schritt

include/RotaryEncoder.h:25:42: error: section attribute not allowed for 'PRELL_PRESSED_MS'
const PROGMEM int PRELL_PRESSED_MS = 500; // Entprellen
 
In file included from src/TeensyDisplay.cpp:4:0:
include/TeensyDisplay.h:25:38: error: section attribute not allowed for 'DEF_FONT'
const PROGMEM int DEF_FONT     = 0;

include/TeensyDisplay.h:26:38: error: section attribute not allowed for 'FONT_HEIGHT'
const PROGMEM int FONT_HEIGHT  = 8;

...

Compiling .pio/build/teensy40/FrameworkArduino/DMAChannel.cpp.o
Compiling .pio/build/teensy40/FrameworkArduino/EventResponder.cpp.o
Compiling .pio/build/teensy40/FrameworkArduino/HardwareSerial.cpp.o
In file included from src/main.cpp:25:0:
include/TeensyDisplay.h:25:38: error: section attribute not allowed for 'DEF_FONT'
const PROGMEM int DEF_FONT     = 0;

Seems to be related to the const attribute but I don't understand the problem - any hint how to fix it would be nice.

Thanks!
For single integer values, you should not be using 'PROGMEM' at all. Just use 'const'.

Going back in history, 'PROGMEM' comes from microprocessors like the Arduino 8-bit AVR processors (like the Uno), had what is called a modified 'Harvard' architecture (as compared to a 'von Neumann' architecture that is used in ARM processors like the Teensy LC/3.x/4.0). The Harvard architecture (from the Harvard Mark I relay computer, built in 1944) has separate memories for data and program. The von Neumann architecture (from the EDVAC computer designed by von Neumann in Princeton in 1945) has a single address space for both program and ata.

The AVR processors do not have much read/write SRAM (the ATiny85 for instance only has 512 bytes of SRAM memory, and the ATmega328p used in the UNO has 2,048 bytes of memory), but they have somewhat more read-only flash memory. Because it is a Harvard architecture, you can't just use a pointer to read data from the program memory, but instead you have to call a function to access the data from the flash memory. Thus for these machines with small SRAM, you want to put read-only tables and strings into program memory, and only copy the items you need into SRAM. For example if you are printing a string literal, you would arrange for the string literal to go into read-only flash memory, and then call an output function that does the operation to bring the string literal into SRAM on the stack, print that, and then reuse the space when the function returns.

The ARM processors put every thing into the same address space (but different regions of addresses have different characteristics). The Teensy 3.x/LC processors just defined 'PROGMEM' to be nothing. The Teensy 4.0 has a more complicated memory layout, and it uses 'PROGMEM' to control the sections things are put into. Because the values are const integer scalars at file scope level, the C++ compiler does not actually allocate space for them, but just uses the constant internally, so an attribute that specifies the storage section (i.e. PROGMEM) does not make sense. If you used the older C language, due to different rules for const, it would allocate the scalar value to read-only memory, and the compiler would not typically just use the constant, and instead load it from memory. However, since the Arduino IDE is built on C++, C is not an issue for .ino sketches.

Now, the compiler has a restriction that you can't have data items and functions in the same section. So if you intermix some new Teensy4 functions that might be declared with 'PROGMEM' along with older code that came from the AVR that uses 'PROGMEM' on data arrays and string literals, the compiler will complain about inter-mixing the two. It has been talked about due to this restriction, that perhaps we should change the 'PROGMEM' used on some new Teensy4 functions to some other new macro.

So going forward:
  • If you are only programing Teensys or other ARM processors, get rid of 'PROGMEM' completely, and just use 'const' or 'static const' for initializations of arrays at file scope level;
  • If you do need to run on both AVRs and ARMs, be sure to test the code on both platforms, as the syntax can get tricky;
  • Do not use 'PROGMEM' on scalar values ever.
 
Status
Not open for further replies.
Back
Top