Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 7 of 7

Thread: Teensy 4.0 - section attribute not allowed

Hybrid View

  1. #1
    Junior Member
    Join Date
    Feb 2019
    Location
    Cologne, Germany
    Posts
    12

    Teensy 4.0 - section attribute not allowed

    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!

  2. #2
    Junior Member
    Join Date
    Aug 2018
    Location
    Brisbane, Australia
    Posts
    1
    the meaning of PROGMEM is different in 4.0 vs 3.x

  3. #3
    Junior Member
    Join Date
    Feb 2019
    Location
    Cologne, Germany
    Posts
    12
    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 by webline; 08-29-2019 at 08:15 AM.

  4. #4
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    5,414
    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.

  5. #5
    Junior Member
    Join Date
    Feb 2019
    Location
    Cologne, Germany
    Posts
    12
    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 by webline; 08-29-2019 at 02:44 PM.

  6. #6
    Senior Member+ MichaelMeissner's Avatar
    Join Date
    Nov 2012
    Location
    Ayer Massachussetts
    Posts
    3,248
    Quote Originally Posted by webline View Post
    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.

  7. #7
    Junior Member
    Join Date
    Feb 2019
    Location
    Cologne, Germany
    Posts
    12
    @MichaelMeissner I'm very impressed. That was a great explanation! Thanks a lot for this outstanding post.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •