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

Thread: Teensy 4.x: F() ? how to keep strings in flash and not in the ITCM?

  1. #1
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    10,341

    Teensy 4.x: F() ? how to keep strings in flash and not in the ITCM?

    Supposed we have a constant table of items that also contain strings, that we would like to keep out of the ITCM or DTCM memory how best to do it?

    Example:
    Code:
    PROGMEM static const struct chipinfo {
    	uint8_t id[3];
    	uint8_t addrbits;	// number of address bits, 24 or 32
    	uint16_t progsize;	// page size for programming, in bytes
    	uint32_t erasesize;	// sector size for erasing, in bytes
    	uint8_t  erasecmd;	// command to use for sector erase
    	uint32_t chipsize;	// total number of bytes in the chip
    	uint32_t progtime;	// maximum microseconds to wait for page programming
    	uint32_t erasetime;	// maximum microseconds to wait for sector erase
    	const char *pn;		//flash name
    } known_chips[] = {
    	//NAND
    	//{{0xEF, 0xAA, 0x21}, 24, 2048, 131072, 134217728,   2000, 15000},  //Winbond W25N01G
    	//Upper 24 blocks * 128KB/block will be used for bad block replacement area
    	//so reducing total chip size: 134217728 - 24*131072
        {{0xEF, 0xAA, 0x21}, 24, 2048, 131072, 0, 131596288, 2000, 15000, "W25N01GVZEIG"},  //Winbond W25N01G
    	//{{0xEF, 0xAA, 0x22}, 24, 2048, 131072, 134217728*2, 2000, 15000},  //Winbond W25N02G
    	{{0xEF, 0xAA, 0x22}, 24, 2048, 131072, 0, 265289728, 2000, 15000, "W25N02KVZEIR"},  //Winbond W25N02G
        {{0xEF, 0xBB, 0x21}, 24, 2048, 131072, 0, 265289728, 2000, 15000, "W25M02"},  //Winbond W25M02
    };
    If I remember correctly the known_chips array will stay in flash, but those strings will not....

    I thought one solution to this was using the F() were setup to do this...
    like:
    Code:
    	{{0xEF, 0xAA, 0x22}, 24, 2048, 131072, 0, 265289728, 2000, 15000, F("W25N02KVZEIR")},  //Winbond W25N02G
    This leads to a compiler error saying, it can not convert a (const __FlashStringHelper *) to a (const char *)
    You can fix this error by casting...

    However this still does not appear to leave the string in flash...
    At least if I run the sketch:

    Code:
    void setup()
    {
      while (!Serial) ;
      Serial.begin(115200);
    
      const char *p;
    
      p = "abcd";
      Serial.printf("%p - %s\n", (uint32_t)p, p);
    
      p = (const char *)F("efgh");
      Serial.printf("%p - %s\n",  (uint32_t)p, p);
    
      const __FlashStringHelper *pf = F("ijkl");
      Serial.printf("%p - %s\n",  (uint32_t)pf, pf);
    }
    
    void loop() { }
    Output:
    Code:
    0x200004b8 - abcd
    0x200004cc - efgh
    0x200004d4 - ijkl
    Note: if I add
    Code:
    const char PROGMEM name1[] = "In Flash";
    ...
      p = name1;
      Serial.printf("%p - %s\n",  (uint32_t)p, p);
    Code:
    0x200004b8 - abcd
    0x200004cc - efgh
    0x200004d4 - ijkl
    0x60001aa4 - In Flash
    So is the only way to do the table with keeping strings out of memory to either
    a) define the strings as individual strings like I mentioned and reference them
    b) or maybe instead of structure having (const char *) instead have const char[10] where the 10 is size of largest one

    Am I missing something obvious?

    Edit, should mention this run was using MMOD

  2. #2
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    26,218
    For global variables, I do not know of any way to use the convenient "string literal" syntax for a char pointer. I believe both of the ways you mentioned work, though using the fixed array size means always allocating the maximum size. But it always avoids allocating 4 bytes for a pointer, so maybe a good trade-off for small strings.

  3. #3
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    10,341
    Quote Originally Posted by PaulStoffregen View Post
    For global variables, I do not know of any way to use the convenient "string literal" syntax for a char pointer. I believe both of the ways you mentioned work, though using the fixed array size means always allocating the maximum size. But it always avoids allocating 4 bytes for a pointer, so maybe a good trade-off for small strings.
    Thanks Paul, but not sure what the F() is doing, for example in the sketch I mentioned...

    I would have thought that:
    Code:
     const __FlashStringHelper *pf = F("ijkl");
      Serial.printf("%p - %s\n",  (uint32_t)pf, pf);
    Would have shown the address(0x200004d4 ) would be up still in flash, but instead it is showing in ITCM correction DTCM

  4. #4
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    15,870
    Extended the last two strings beyond 4 characters and both still sit sequentially in ITCM:
    Code:
    0x200008ac - abcd
    0x200008c0 - efgh
    0x200008dc - ijkl
    0x200008c8 - efghIJKLMN
    0x200008d4 - ABCDEFGHijkl
    Code:
      p = (const char *)F("efghIJKLMN");
      Serial.printf("%p - %s\n",  (uint32_t)p, p);
    
      const __FlashStringHelper *pf2 = F("ABCDEFGHijkl");
      Serial.printf("%p - %s\n",  (uint32_t)pf2, pf2);
    Doing this puts it in a different segment group - but not FLASH:
    Code:
      const char SzSZ[] = "efghIJKLMN";
      Serial.printf("const char SzSZ[]: %p - %s\n",  SzSZ, SzSZ);
    Code:
    const char SzSZ[]: 0x20077fd4 - efghIJKLMN

  5. #5
    Senior Member
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    1,811
    Deleted because the proposed method doesn't really work...

  6. #6
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    15,870
    Some variations are causing errors like:
    Code:
    error: section attribute cannot be specified for local variables
    
    error: known_chips causes a section type conflict with SzSZ
    Odd not that they aren't legal expressions - but given prior expressions these can't be used in the same compilation part?

  7. #7
    Senior Member
    Join Date
    Apr 2014
    Location
    -
    Posts
    9,756
    Quote Originally Posted by defragster View Post
    Some variations are causing errors like:
    Code:
    error: section attribute cannot be specified for local variables
    
    error: known_chips causes a section type conflict with SzSZ
    Odd not that they aren't legal expressions - but given prior expressions these can't be used in the same compilation part?
    As local vars are on the stack, a section makes no sense

    note, worst is to define a const array inside a function.
    GCC will use a memcpy to copy it to the stack if you use it.. - have seen that - the worst thing i can imagine But hey, it just does what the user tells it to do..

  8. #8
    Quote Originally Posted by Frank B View Post
    note, worst is to define a const array inside a function. GCC will use a memcpy to copy it to the stack if you use it.
    Would static const array be okay? That should scope but not be on the stack.

  9. #9
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    10,341
    Quote Originally Posted by Frank B View Post
    As local vars are on the stack, a section makes no sense

    note, worst is to define a const array inside a function.
    GCC will use a memcpy to copy it to the stack if you use it.. - have seen that - the worst thing i can imagine But hey, it just does what the user tells it to do..
    I have it now doing such like:
    Code:
    	const char * getPN() { 
    		PROGMEM static const char pn_name[] = "PROGRAM";
    		return pn_name; 
    	}
    And have output:
    Code:
    Dump Storage list(7)
    store:0 storage:10001 name:Program fs:200059f0 pn:PROGRAM(0x6000373c)
    store:1 storage:20001 name:RAM fs:20005abc pn:DMAMEM(0x60003744)
    store:2 storage:30001 name:Flash_3 fs:20005b88 pn:W25Q128JV*Q/W25Q128FV(0x60003878)
    store:3 storage:40001 name:NAND_4 fs:20005e50 pn:W25N01GVZEIG(0x60003c54)
    store:4 storage:50001 name:Flash_5 fs:20006118 pn:W25Q512JV*M (DTR)(0x60003a18)
    store:5 storage:60001 name:SD_Builtin fs:20006cbc pn:(0x200017a0)
    store:6 storage:70001 name:SD_SPI fs:2000718c pn:(0x200017a0)
    And you can see address of the string return is 0x6000373c which is up in flash...

  10. #10
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    15,870
    Quote Originally Posted by Frank B View Post
    As local vars are on the stack, a section makes no sense

    note, worst is to define a const array inside a function.
    GCC will use a memcpy to copy it to the stack if you use it.. - have seen that - the worst thing i can imagine But hey, it just does what the user tells it to do..
    Sorry, code not included - those are with defines outside the func() - cannot use PROGMEM within a func()

    New var char szSZ2 in one case conflicted with independent szSZ, The second szSZ conflicted with prior @mjs513 code where I was inserting this demo code.
    > from FS thread : \LFS_PN_Test\LFS_PN_Test.ino

Posting Permissions

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