Forum Rule: Always post complete source code & details to reproduce any issue!
Page 2 of 4 FirstFirst 1 2 3 4 LastLast
Results 26 to 50 of 77

Thread: T4.0 Memory - trying to make sense of the different regions

  1. #26
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    20,825
    EDIT: quick recap from msg #24: working to solve these 3 issues:

    1: Clear & easy to understand documentation is needed
    2: Arduino's size info doesn't fit the memory model
    3: PROGMEM can't be used for both code & data in the same file

    -------------------------------

    I've added a "Memory Layout" section to the Teensy 4.0 product page.

    I tried to explain it from the programming point of view, with some notes near the end about the hardware considerations. I mentioned the DMA issues briefly, but I'm feeling like DMA usage wants to be another page (and those words will become a link to it).

    I shied away from discussing the low-level details of FlexRAM config, other than mentioning 32K round up and small unused space. Hopefully emphasizing how you actually use the memory from code, and de-emphasizing the hardware config, will help the most people?

    Please let me know what you think?
    Last edited by Paul; 10-23-2019 at 11:35 PM. Reason: Add 3 issues, from msg #24 on prior page

  2. #27
    Senior Member
    Join Date
    May 2015
    Location
    San Francisco
    Posts
    196
    Thanks, Paul, that's super useful and clear.

    A couple of thoughts:

    Would it be possible to add the default values for the various fixed addresses?

    One note on the graphic: I puzzled over why there was an arrow from DMAMEM to FASTRUN code for a couple of seconds, then I realized that the arrow goes under the RAM2 block. Maybe rearrange the columns in the diagram to go from left to right: Flash, RAM1, RAM2 with the arrows going from left to right...

    Would it also be possible to put in a few lines of example code showing how to mark items to be loaded into the appropriate sections?

  3. #28
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    5,738
    Looks good.

    I agree that DMA will need a lot more explanation, probably as it's own topic.

    Currently isn't all code more or less fastrun? If not, hopefully we can make that change.

    This might cause some of us to want to take a quick pass through several of the libraries and try to decide which parts if any should be fastrun.

    It will be interesting to figure out what makes sense to try to make fastrun.

    First I assume that there is no such thing like:
    Code:
    extern "FASTRUN" {
    ...
    }
    My guess is many of the initialization like functions that are typically only called once would not be marked FASTRUN.

    Also probably things like ISRs should be marked FASTRUN.

    But what about things like: ILI9341_t3::fillRect? Yes you might want this to run FAST, but it is mainly limited by SPI output speed...

    Now of course it can be more confusing if you then go to ILI9341_t3n, where you can turn on a Frame buffer. In this case where you are simply filling memory, than maybe yes you want it to run fast.

    BUT, maybe this depends on the sketch using it? That is should I as a sketch developer decide, do I want these functions sped up and the expense of reducing my memory available for data variables...


    Again your T4 page helps explain a lot of details without getting to deep into some of the underlying hardware.

  4. #29
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    10,106
    I did a quick scan of the 'Memory Layout' - looks very good. @KurtE - would be good to add to OP if not already done.

    @KurtE - as I understand and from the startup memcopy it seems Any code not PROGMEM gets brought into the RAM1 area on startup.

    Quote Originally Posted by blackketter View Post
    Thanks, Paul, that's super useful and clear.

    A couple of thoughts:

    Would it be possible to add the default values for the various fixed addresses?

    One note on the graphic: I puzzled over why there was an arrow from DMAMEM to FASTRUN code for a couple of seconds, then I realized that the arrow goes under the RAM2 block. Maybe rearrange the columns in the diagram to go from left to right: Flash, RAM1, RAM2 with the arrows going from left to right...

    Would it also be possible to put in a few lines of example code showing how to mark items to be loaded into the appropriate sections?
    I agree the pictorial representation isn't clear with those vanishing arrow lines. Perhaps put the FLASH memory SPACE in the MIDDLE and the RAM1 on the LEFT with arrow to where it resides and them the RAM2 on the right showing it is detacahed from FLASH startup and it RunTime RAM?

    Also yes - having the picture show the "default values for the various fixed addresses" for the key areas would be helpful. Also is there a way at runtime to know where the 'Unused Flash' area starts? Startup could make a 'global' pointer to the space after 'Initialized Variables'

  5. #30
    Senior Member DD4WH's Avatar
    Join Date
    Oct 2015
    Location
    Central Europe
    Posts
    508
    @Paul: thanks a lot for the graph and the explanation! That is what I have been waiting for :-).

    It was very hard (and still is hard) to understand how the memory is composed and especially how to use the different regions.

    I run into problems when using my SDR code when I tried to use more than 512kb, although I put all the big data arrays into DMAMEM.

    Now from the graph I understand it could be due to local variables (arrays) in functions that could cause my RAM1 region to overflow when those functions are called!?

    Can I tell the compiler to leave code in PROGMEM and not copy it to the FASTRUN region or tell the compiler to only put specific functions into FASTRUN? That could leave enough room in RAM1 for the local variables . . . I think

    As others noted, it would be good to know the syntax of how to assign parts of code to the different regions, at the moment I use trial & error like this, but I have no idea whether that does what it should:

    Code:
    float32_t DMAMEM FFT_spec[256];
    But how can I tell the compiler to put functions into FASTRUN or to leave them in FLASH?

    Thanks a lot for the help!

    Frank DD4WH

  6. #31
    Senior Member
    Join Date
    Jul 2014
    Posts
    2,398
    Quote Originally Posted by PaulStoffregen View Post
    Please let me know what you think?
    My interest is only to learn how I could use all the memory available. If I have to DMA or dynamic allocation or something else.
    The new picture seems to be what I was expecting.

  7. #32
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    5,738
    Quote Originally Posted by defragster View Post
    I did a quick scan of the 'Memory Layout' - looks very good. @KurtE - would be good to add to OP if not already done.
    Sorry @defragster - My mind is still on vacation OP?

    Quote Originally Posted by defragster View Post
    @KurtE - as I understand and from the startup memcopy it seems Any code not PROGMEM gets brought into the RAM1 area on startup.
    Yes - the startup.c ResetHandler function does this:
    Code:
    void ResetHandler(void)
    {
    	unsigned int i;
    
    #if defined(__IMXRT1062__)
    	IOMUXC_GPR_GPR17 = (uint32_t)&_flexram_bank_config;
    	IOMUXC_GPR_GPR16 = 0x00000007;
    	IOMUXC_GPR_GPR14 = 0x00AA0000;
    	__asm__ volatile("mov sp, %0" : : "r" ((uint32_t)&_estack) : );
    #endif
    	// pin 13 - if startup crashes, use this to turn on the LED early for troubleshooting
    	//IOMUXC_SW_MUX_CTL_PAD_GPIO_B0_03 = 5;
    	//IOMUXC_SW_PAD_CTL_PAD_GPIO_B0_03 = IOMUXC_PAD_DSE(7);
    	//IOMUXC_GPR_GPR27 = 0xFFFFFFFF;
    	//GPIO7_GDIR |= (1<<3);
    	//GPIO7_DR_SET = (1<<3); // digitalWrite(13, HIGH);
    
    	// Initialize memory
    	memory_copy(&_stext, &_stextload, &_etext);
    	memory_copy(&_sdata, &_sdataload, &_edata);
    	memory_clear(&_sbss, &_ebss);
    First it copies the Program code (ITCM), then it copies in the DTCM stuff that is initialized, and then it zeros the other variables.

    EDIT: So the interesting question is, for things that are only run once (or a few times) what is timing difference between running it from Flash versus copy it from Flash to ITCM to then run it?

    @DD4WH - You can mark functions to be FASTRUN. Example:
    Code:
    FASTRUN
    void irq_gpio1(void)
    {
    	irq_anyport(&GPIO1_DR, isr_table_gpio1);
    }
    However at least the last time I looked on T4 all of the code is currently FASTRUN, except for the hack I mentioned in a previous post where you could mark a function as PROGMEM which would leave it in FLASH. But as I mentioned there is/was an issue you could not have DMAMEM for both code and data...

  8. #33
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    5,738
    @Paul - Again I am not sure how many people it would help, but I know a few people have asked about the addressing of these different areas.

    @all...

    If you look at chapter 2 of the IMXRT manual you will see an ARM Platform Memory map: So key addressing to look at:
    ITCM starts at address: 0x00000000
    DTCM Starts at address: 0x20000000
    OCRAM2 starts at address: 0x20200000
    Flash(FlexSPI) : 0x60000000

  9. #34
    Senior Member DD4WH's Avatar
    Join Date
    Oct 2015
    Location
    Central Europe
    Posts
    508
    Thanks Kurt! I still have problems understanding the syntax . . .

    Maybe it would be good to give some dummy examples and let you experts comment on that ?

    Is the following syntax/use example correct?

    I want to use most of the RAM and thus I place variables in DMAMEM:
    Code:
    DMAMEM
    float32_t my_array[1024]
    But I cannot additionally have this ?:
    Code:
    DMAMEM
    void my_function_in_dmamem (void) {}
    I want a slow function
    Code:
    PROGMEM
    void my_slow_function {
    // do something
    }

    I want a very fast function
    Code:
    FASTRUN
    void my_fast_function (void)
    {
    }
    This could create problems of overflow of RAM1 !?
    Code:
    void my_function_with_very_large_local_variables (void)
    {
    static float my_absurdely_large_array [256000];
    }

  10. #35
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    10,106
    Quote Originally Posted by KurtE View Post
    Sorry @defragster - My mind is still on vacation OP?


    Yes - the startup.c ResetHandler function does this:
    ...
    First it copies the Program code (ITCM), then it copies in the DTCM stuff that is initialized, and then it zeros the other variables.

    EDIT: So the interesting question is, for things that are only run once (or a few times) what is timing difference between running it from Flash versus copy it from Flash to ITCM to then run it?

    @DD4WH - You can mark functions to be FASTRUN. Example:
    ...However at least the last time I looked on T4 all of the code is currently FASTRUN, except for the hack I mentioned in a previous post where you could mark a function as PROGMEM which would leave it in FLASH. But as I mentioned there is/was an issue you could not have DMAMEM for both code and data...
    @KurtE - OP == Original Post

    Yes, that is the FLASH copy code to RAM1 as noted.

    After those copes it could set a Global pointer to pFreeFlash for anyone wanting to use the Free Flash area for work area …. until the next upload.

    @Paul: Might be worth noting that ALL of Flash under EEPROM/RESET is wiped on each upload

    Indeed Paul notes the DMAMEM area is DATA only as marked, NO Execute

    PROGMEM gets a complaint when in the same compile unit both Code and Data are marked PROGMEM - it seemed an alternate name would be needed to marking one or the other so both can be left on FLASH?

    Those p#33 address would be nice to have on the picture on the T4 Memory Layout. Including the spot where the low end of EEPROM.

    In scanning the Newest USB Code just on Github yesterday some of those elements were marked 'PROGMEM' - IIRC it was the USB Descriptors that would have no or perhaps generally one time use.

    For reference: All code on the T_3.6 runs from FLASH - except a smaller RAM cache area that can be used with FASTRUN, or may hold recent Flash code. But the T_3.6 F_CPU doesn't outpace the FLASH read rate as much.
    - the T_3.6/3.5 Flash is internal and 8 bit or better? What is the FLASH connect to the T_4 QSPI or better?
    > The T4 has a larger dedicated cache than the T_3.6 that will hold code the MCU decides to leave there for use.

  11. #36
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    20,825
    Quote Originally Posted by defragster View Post
    I agree the pictorial representation isn't clear with those vanishing arrow lines.
    How about this? Does it help?




    Perhaps put the FLASH memory SPACE in the MIDDLE and the RAM1 on the LEFT with arrow to where it resides and them the RAM2 on the right showing it is detacahed from FLASH startup and it RunTime RAM?
    That'll take much more work since it's drawn with the Gimp using many layers.

  12. #37
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    20,825
    Quote Originally Posted by blackketter View Post
    Would it also be possible to put in a few lines of example code showing how to mark items to be loaded into the appropriate sections?
    Yes, some examples are needed. But first I want to look at issue #3 (from msg #24) before adding examples to the documentation. If we need to add a 2nd keyword for PROGMEM, I'll need to update some of the stuff that's already written & drawn, and it'll impact the examples. Especially with examples, I've been burned before by writing prematurely and then they didn't work when people would copy & paste the example code.

  13. #38
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    20,825
    Quote Originally Posted by DD4WH View Post
    Can I tell the compiler to leave code in PROGMEM and not copy it to the FASTRUN region or tell the compiler to only put specific functions into FASTRUN? That could leave enough room in RAM1 for the local variables . . . I think
    ....
    But how can I tell the compiler to put functions into FASTRUN or to leave them in FLASH?
    Yes, you can control this by putting FASTRUN on every function you want to RAM1 and PROGMEM on every function you want in flash.

    If you don't use either, then it's up to the compiler (actually, the linker script) to decide. Today all unspecified functions go into RAM1, to optimize performance at the cost of RAM. At some point in the (likely distant) future, we may have an alternate linker script which causes all the unspecified functions to go into Flash. Maybe there might even eventually be a way to select which scheme to use from the Arduino > Tools menus.

    But you absolutely do get to control which way they are allocated. That's what the FASTRUN and PROGMEM labels do.

  14. #39
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    20,825
    Quote Originally Posted by KurtE View Post
    So the interesting question is, for things that are only run once (or a few times) what is timing difference between running it from Flash versus copy it from Flash to ITCM to then run it?
    This sounds like a question best answered by a couple digitalWriteFast() lines and a logic analyzer.


    Quote Originally Posted by KurtE View Post
    @Paul - Again I am not sure how many people it would help, but I know a few people have asked about the addressing of these different areas.

    @all...

    If you look at chapter 2 of the IMXRT manual you will see an ARM Platform Memory map: So key addressing to look at:
    ITCM starts at address: 0x00000000
    DTCM Starts at address: 0x20000000
    OCRAM2 starts at address: 0x20200000
    Flash(FlexSPI) : 0x60000000
    I intentionally left these sorts of details out, with the hope that the more essential information would be easier to understand.

    Maybe a brief mention and link to the reference manual would help?

  15. #40
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    5,738
    Quote Originally Posted by defragster View Post
    @KurtE - OP == Original Post
    Good Idea, Done... Thanks

    Quote Originally Posted by defragster View Post
    After those copes it could set a Global pointer to pFreeFlash for anyone wanting to use the Free Flash area for work area …. until the next upload.

    @Paul: Might be worth noting that ALL of Flash under EEPROM/RESET is wiped on each upload
    Not sure what you are asking/suggesting?

    Are you simply saying that programs, could try to muck with flash storage that is above the flash memory that sketch used?

    You could probably already do that with looking at the variable _flashImagelen
    For example in bootdata.c you see:
    Code:
    extern unsigned long _flashimagelen;
    I have not tried it, but my dump info about app, looks for this symbol.

    @DD4WH - Not sure what the proper syntax will be or if it will change.

    That is I can imagine that we could make T4 like T3.x and assume all code will be run from FLASH unless it is marked with FASTRUN. And/Or I can see a new define being put in, like "FLASH" or "FLASHRUN" or ??? which says This one will always be run from Flash, and have compile/linker option that says that unmarked functions will run from Flash or from FAST...

    This is beyond my pay grade ($0) - Something that Paul will need to decide and implement.

  16. #41
    Senior Member+ MichaelMeissner's Avatar
    Join Date
    Nov 2012
    Location
    Ayer Massachussetts
    Posts
    3,375
    Quote Originally Posted by PaulStoffregen View Post
    But you absolutely do get to control which way they are allocated. That's what the FASTRUN and PROGMEM labels do.
    We probably need to come up with an alternate name for PROGMEM for functions, and get it into 1.49, and change all the function declarations in the current source to use this new name.

    Given how historical AVR code uses PROGMEM for data, we should presumably reserve this for data declarations.

  17. #42
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    10,106
    Quote Originally Posted by PaulStoffregen View Post
    How about this? Does it help?

    That'll take much more work since it's drawn with the Gimp using many layers.
    That is a good (enough) improvement having the lines not vanish into and pop out of RAM2.

    Quote Originally Posted by MichaelMeissner View Post
    We probably need to come up with an alternate name for PROGMEM for functions, and get it into 1.49, and change all the function declarations in the current source to use this new name.

    Given how historical AVR code uses PROGMEM for data, we should presumably reserve this for data declarations.
    That would be good if it solves it - Frank B brought this up in Beta as an issue when PROGMEM is 'overused' and some clear workaround alternate would help. It never took off for lack of a good name FLASHRUN


    Quote Originally Posted by KurtE View Post
    Good Idea, Done... Thanks

    Not sure what you are asking/suggesting?

    Are you simply saying that programs, could try to muck with flash storage that is above the flash memory that sketch used?

    You could probably already do that with looking at the variable _flashImagelen
    For example in bootdata.c you see:
    Code:
    extern unsigned long _flashimagelen;
    I have not tried it, but my dump info about app, looks for this symbol.

    ...
    Yes, I think that is what I was looking for - it can be derived in Startup.c - need a public pointer/index to end of used Flash - rounded up to next 32K block?
    Paul once noted that somebody might want this area - and IIRC at least one post asked about a way to store a relatively large set of 'device settings' too large for EEPROM - not often changed after programmed if ever - but needed as a ready 'read only' reference for Hardware Definition for a given installation.

  18. #43
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    5,738
    @defragster - Actually I think I misunderstood your previous question. I don't think you are interested in what is the last address used in the FLASH RAM? (addresses in the 60000000 range), but maybe what memory is still maybe use able in the DTCM region of memory?

    In this Later case, this can sort of be easy.

    That is I believe everything above the address: _edata is unused. Or another way to look at it is everything above there is currently only available for the Stack.
    Which is what my memory usage program that I put in platform.txt file...

    Code:
    cmd /c "D:\\arduino-1.8.10\\hardware\\teensy\\..\\tools\\arm\\bin\\arm-none-eabi-gcc-nm -n C:\\Users\\kurte\\AppData\\Local\\Temp\\arduino_build_974987\\Scanner.ino.elf | D:\\GITHUB\\imxrt-size\\Debug\\imxrt-size.exe"
    
    Again sample output: 
    FlexRAM section ITCM+DTCM = 512 KB
        Config : aaaaaaab
        ITCM :   8640 B	(26.37% of   32 KB)
        DTCM :  12992 B	( 2.64% of  480 KB)
        Available for Stack: 478528
    OCRAM: 512KB
        DMAMEM:      0 B	( 0.00% of  512 KB)
        Available for Heap: 524288 B	(100.00% of  512 KB)
    Flash:  16816 B	( 0.83% of 1984 KB)
    The above is the I2C Scanner program. Which says we have about 478K of memory available to the stack.

    What I thought about doing for my own self is to try to define a simple function: Maybe something like: uint8_t*T4DTCMAlloc(uint32_t size);

    Where maybe the code does something real simple like:
    Code:
    static uint8_t * _freeDTCMStart = &_edata;
    
    uint8_t* T4DTCMAlloc(uint32_t size) {
        uint8_t *ptr = _freeDTCMStart;
        _freeDTCMStart  += size;
        return ptr;
    }
    Which is pretty simple, does not have any validation, nor anyway to return data back. So its an allocate at init type setup.

    This could be extended to add additional checks and the like. For example it could check the value of what the new free ptr would be and if it would be close to the current stack pointer value it would fail. Or maybe it could be called with another conditional parameter, like only succeed if the free space is > X...

    Then maybe update some of the display libraries we have updated to handle DMA updates on T4, by having the code have to copy data from DMA memory to a lower memory buffer to work properly with DMA, to say. OK my buffer is in low memory so I can do simple DMA operations...

    Not sure if that makes sense?

  19. #44
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    10,106
    Speaking of MEMORY - New to CORES on github
    >> avr: pgmspace.h Use DMAMEM for USB serial transmit buffer 12 hours ago
    >> WProgram.h Use DMAMEM for USB serial transmit buffer
    >> usb_serial.c Use DMAMEM for USB serial transmit buffer

    And yesterday added new descriptors to FLASH:: PROGMEM const uint8_t usb_config_descriptor_480[CONFIG_DESC_SIZE] = {

    … going to grab that and see what usb does ...

  20. #45
    Senior Member DD4WH's Avatar
    Join Date
    Oct 2015
    Location
    Central Europe
    Posts
    508
    Quote Originally Posted by KurtE View Post
    @DD4WH - Not sure what the proper syntax will be or if it will change.
    Oh, I was not aware that the syntax is still evolving, that explains a lot.

    For the moment, I tried to reproduce your RAM-Info, but I could not get imxrt-size.cpp to run . . .

    So I put together a RAM-Info-function for dummies like me, maybe helpful for others:

    Code:
    PROGMEM
    void flexRamInfo(void)
    { // credit to FrankB and KurtE and defragster
    #if defined(__IMXRT1052__) || defined(__IMXRT1062__)
      int itcm = 0;
      int dtcm = 0;
      int ocram = 0;
      Serial.print("FlexRAM-Banks: [");
      for (int i = 15; i >= 0; i--) {
        switch ((IOMUXC_GPR_GPR17 >> (i * 2)) & 0b11) {
          case 0b00: Serial.print("."); break;
          case 0b01: Serial.print("O"); ocram++; break;
          case 0b10: Serial.print("D"); dtcm++; break;
          case 0b11: Serial.print("I"); itcm++; break;
        }
      }
      Serial.print("] ITCM: ");
      Serial.print(itcm * 32);
      Serial.print(" KB, DTCM: ");
      Serial.print(dtcm * 32);
      Serial.print(" KB, OCRAM: ");
      Serial.print(ocram * 32);
    #if defined(__IMXRT1062__)
      Serial.print("(+512)");
    #endif
      Serial.println(" KB");
      extern unsigned long _stext;
      extern unsigned long _etext;
      extern unsigned long _sdata;
      extern unsigned long _ebss;
      extern unsigned long _flashimagelen;
      extern unsigned long _heap_start;
    
      Serial.println("MEM (static usage):");
      Serial.println("RAM1:");
    
      Serial.print("ITCM = FASTRUN:      ");
      Serial.print((unsigned)&_etext - (unsigned)&_stext);
      Serial.print("   "); Serial.print((float)((unsigned)&_etext - (unsigned)&_stext) / ((float)itcm * 32768.0) * 100.0);
      Serial.print("%  of  "); Serial.print(itcm * 32); Serial.print("kb   ");
      Serial.print("  (");
      Serial.print(itcm * 32768 - ((unsigned)&_etext - (unsigned)&_stext));
      Serial.println(" Bytes free)");
     
      Serial.print("DTCM = Variables:    ");
      Serial.print((unsigned)&_ebss - (unsigned)&_sdata);
      Serial.print("   "); Serial.print((float)((unsigned)&_ebss - (unsigned)&_sdata) / ((float)dtcm * 32768.0) * 100.0);
      Serial.print("%  of  "); Serial.print(dtcm * 32); Serial.print("kb   ");
      Serial.print("  (");
      Serial.print(dtcm * 32768 - ((unsigned)&_ebss - (unsigned)&_sdata));
      Serial.println(" Bytes free)");
    
      Serial.println("RAM2:");
      Serial.print("OCRAM = DMAMEM:      ");
      Serial.print((unsigned)&_heap_start - 0x20200000);
      Serial.print("   "); Serial.print((float)((unsigned)&_heap_start - 0x20200000) / ((float)512 * 1024.0) * 100.0);
      Serial.print("%  of  "); Serial.print(512); Serial.print("kb");
      Serial.print("     (");
      Serial.print(512 * 1024 - ((unsigned)&_heap_start - 0x20200000));
      Serial.println(" Bytes free)");
    
      Serial.print("FLASH:               ");
      Serial.print((unsigned)&_flashimagelen);
      Serial.print("   "); Serial.print(((unsigned)&_flashimagelen) / (2048.0 * 1024.0) * 100.0);
      Serial.print("%  of  "); Serial.print(2048); Serial.print("kb");
      Serial.print("    (");
      Serial.print(2048 * 1024 - ((unsigned)&_flashimagelen));
      Serial.println(" Bytes free)");
      
    #endif
    }
    This gives similar output as I have seen several times in this thread :-). [example is for the Teensy Convolution SDR sketch where all the large arrays are assigned to DMAMEM]

    Code:
    FlexRAM-Banks: [DDDDDDDDDDIIIIII] ITCM: 192 KB, DTCM: 320 KB, OCRAM: 0(+512) KB
    MEM (static usage):
    RAM1:
    ITCM = FASTRUN:      171248   87.10%  of  192kb     (25360 Bytes free)
    DTCM = Variables:    103104   31.46%  of  320kb     (224576 Bytes free)
    RAM2:
    OCRAM = DMAMEM:      192864   36.79%  of  512kb     (331424 Bytes free)
    FLASH:               228064   10.87%  of  2048kb    (1869088 Bytes free)
    Thanks all for your help!

  21. #46
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    20,825
    Quote Originally Posted by MichaelMeissner View Post
    We probably need to come up with an alternate name for PROGMEM for functions
    Yup. I was really hoping to avoid adding another #define which could possibly conflict with existing libs & programs. I've just spent several hours looking into this (with objdump and readelf on the generated files) and it seems there is no way around this. The compiler always sets the EXEC flag if it's a function and never sets EXEC if it's a variable, and simply will not allow the same object file to have symbols with the same section name but differing section flags.

    So a call needs to be made. I'm tentatively going with FLASHMEM.

    I did some searching of all source on github, and I was relieved to find most of the uses of "FLASHMEM" (all caps) seem to be similar section defs.

    https://github.com/fdivitto/ESPWebFr.../src/fdv.h#L38

    However, there are some cases were authors have used the same name for a typedef.

    https://github.com/FlameN/STM32RUNO/...rmemory.h#L188

    But in the first 10 pages of github search, I found many more uses of ESPWebFramework's convention, which is a nice sign we can probably go with FLASHMEM for this use.

    Given how historical AVR code uses PROGMEM for data, we should presumably reserve this for data declarations.
    Yes, or at least document it that way and make sure the examples use it that way.

    But I can't find any way to restrict PROGMEM to only variables and FLASHMEM to only functions. Even though gcc has 3 distinct categories of attributes (functions vs variables vs types) they all use the same "__attribute__" keyword, and both the function and variable use cases have the same "section" attribute. It seems the gcc developers are loathe to add new distinct keywords, which is why we're able to use PROGMEM for these 2 cases which probably should be syntactically distinct. Oh well.

    I'm going to commit FLASHMEM and start testing here. If it looks good and nobody raises any serious issues, will put together a first 1.49 beta later this week.

  22. #47
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    4,310
    @PaulStoffregen

    Was tied up yesterday and just popping on and off line and started reading this in earnest this morning. Wow. Thank you for putting the memory mapping and explaining the memory regions. Really helps to visualize the structure and understanding of the memory regions.

    Sure going to have more questions but still on my first cup of coffee.

  23. #48
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    5,738
    Quote Originally Posted by PaulStoffregen View Post
    I'm going to commit FLASHMEM and start testing here. If it looks good and nobody raises any serious issues, will put together a first 1.49 beta later this week.
    Sounds good, I just sunk up my cores and copied them into my 1.8.10 Teensyduino install, and will start playing with it.

    And yes it would be great if there was some descriptions about that on Teensy pages (or WIKI) or ... that describes them, suggestions on how/when to use them...

    Example currently I believe FASTRUN does not mean anything on T4? So should we mark any functions/methods with it such that maybe the linking script(s) might change or be added that switches the unmarked functions from one section to the other?

    Again good stuff!

  24. #49
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    20,825
    For 1.49-beta1, I'm going to change the "Global variables use..." summary to show on RAM1.

    I've opened an issue to ask Arduino to make the memory usage more configurable.

    https://github.com/arduino/arduino-builder/issues/343

    If they agree, maybe we'll go with RAM1 only for now. Or maybe I'll hack the Java code to make it print another line with RAM2. Sadly, there's simply no easy answer when we have 3 distinct memory regions and Arduino's software is hard-coded to print usage of only 2.

  25. #50
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    5,738
    @Paul - I don't know if it makes sense to simply add another utility in the build process, that displays more information.

    I followed I think it was @Frank B who originally did it, but I simply added another line to platform.txt...
    Code:
    recipe.hooks.postbuild.4.pattern.windows=cmd /c "{runtime.hardware.path}\..\tools\arm\bin\arm-none-eabi-gcc-nm -n {build.path}\{build.project_name}.elf | D:\GITHUB\imxrt-size\Debug\imxrt-size.exe"
    Which I know is outputting far too cryptic of data for most people, like recent run of testing the IO pins of the solderless breakout board...

    Code:
    "D:\\arduino-1.8.10\\hardware\\teensy/../tools/teensy_post_compile" -file=HiLowTest.ino "-path=C:\\Users\\kurte\\AppData\\Local\\Temp\\arduino_build_664799" "-tools=D:\\arduino-1.8.10\\hardware\\teensy/../tools/" -board=TEENSY40
    cmd /c "D:\\arduino-1.8.10\\hardware\\teensy\\..\\tools\\arm\\bin\\arm-none-eabi-gcc-nm -n C:\\Users\\kurte\\AppData\\Local\\Temp\\arduino_build_664799\\HiLowTest.ino.elf | D:\\GITHUB\\imxrt-size\\Debug\\imxrt-size.exe"
    
    FlexRAM section ITCM+DTCM = 512 KB
        Config : aaaaaaab
        ITCM :   8240 B	(25.15% of   32 KB)
        DTCM :  12992 B	( 2.64% of  480 KB)
        Available for Stack: 478528
    OCRAM: 512KB
        DMAMEM:   8272 B	( 1.58% of  512 KB)
        Available for Heap: 516016 B	(98.42% of  512 KB)
    Flash:  15264 B	( 0.75% of 1984 KB)
    Note: my program returns an error code if it finds that ITCM+DTCM would exceed the 512KB...
    Also a couple of posts up, @DD4WH made a version of it with a little less cryptic output...

    But yes, I think RAM1 is better than the current stuff, although I can also imagine there will be some complaining about, I thought I purchased a board with 1mbs of memory why is there only 512KB...

Posting Permissions

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