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

Thread: Trying to understand why my code takes up so much RAM1

  1. #1

    Trying to understand why my code takes up so much RAM1

    Hey!

    Because I am quite near the memory limits (after 2 iterations of trying to get it smaller) I would like to understand what areas of code take up what parts of the memory. I add some example code, maybe that helps me understand all that a little bit better

    Code:
    uint32_t global_var = 0; // takes up 4 bytes in RAM 1 because it is global
    
    struct TestStruct {
      uint32_t a;
      uint32_t b;
      uint32_t c;
      uint32_t d;
    }; // where does the definition of this struct go?
    
    TestStruct* test_struct_ptr = 0; // takes up 4 Byte in RAM1 als pointer to the memory?
    
    FLASHMEM void flash_func() {
      // with content
    } // stays ins flash memory and does not take up RAM1 right?
    
    void main() {
      test_struct_ptr = new TestStruct(); // takes up 16 bytes in RAM2 because it’s allocated dynamically
    } // main is going to the start of RAM1 because of FASTRUN or at least somewhere else in RAM1?
    I refactored as much Strings as somehow possible for the UI to be F(), I have every function in my UI classes as FLASHMEM function. All the dynamic project data (Tracks, Instrument-Configurations, tons of Notes- and Modulation data) is dynamically allocated into PSRAM. The structs that hold that data have some helper functions, mostly for initialization and for the UI. Those are marked as FLASHMEM also. All the UI -relevant classes are dynamically created during runtime to keep it away from RAM1.

    and still I use up newly all of the available memory and receive that compile error from time to time when I am hitting the limit. Yes it’s a lot of Code (Drawing all those individual screens and every screen needs custom IO -event handling, but still, can that be over 300k of Code?
    Is there a way to Analyse the code to see what functions and what classes/structs take up how much space?

    maybe this helps me to find the part, where I might be doing something wrong or where I could change it, so I can continue to add features.

  2. #2
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    17,137
    Seems like PJRC's Teensy 4 / 4.1 MEMORY storage info web page has been found indicating the keywords to use?

    This info from building gives a snapshot of allocations:
    Code:
    teensy_size: Memory Usage on Teensy 4.1:
    teensy_size:   FLASH: code:37248, data:5016, headers:8932   free for files:8075268
    teensy_size:    RAM1: variables:6080, code:34624, padding:30912   free for local variables:452672
    teensy_size:    RAM2: variables:12384  free for malloc/new:511904
    Where padding can be up towards 32KB of unused space depending on the code space used in RAM1/ITCM. In the case above getting rid of ~2KB of code would return 32KB of RAM1 for DTCM.

    Looking in the temp Build folder will have a .SYM file that shows locations of the named parts of the code.

  3. #3
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    17,137
    The definition goes away during compile - but below:: 200012bc g O .bss 00000004 test_struct_ptr

    Building:
    Code:
    uint32_t global_var = 0; // takes up 4 bytes in RAM 1 because it is global
    
    struct TestStruct {
      uint32_t a;
      uint32_t b;
      uint32_t c;
      uint32_t d;
    }; // where does the definition of this struct go?
    TestStruct* test_struct_ptr = 0; // takes up 4 Byte in RAM1 als pointer to the memory?
    
    FLASHMEM void flash_func() {
      // with content
    } // stays ins flash memory and does not take up RAM1 right?
    
    void setup() {
      // put your setup code here, to run once:
      Serial.begin(115200);
      while (!Serial && millis() < 4000 );
      Serial.println("\n" __FILE__ " " __DATE__ " " __TIME__);
      test_struct_ptr = new TestStruct(); // takes up 16 bytes in RAM2 because it’s allocated dynamically
    
    }
    
    void loop() {
      // put your main code here, to run repeatedly:
    
    }
    gives:
    Code:
    teensy_size: Memory Usage on Teensy 4.1:
    teensy_size:   FLASH: code:12412, data:3992, headers:9192   free for files:8100868
    teensy_size:    RAM1: variables:4896, code:9792, padding:22976   free for local variables:486624
    teensy_size:    RAM2: variables:12384  free for malloc/new:511904
    and
    Code:
    R:\temp\arduino_build_SymInfo.ino/SymInfo.ino.elf:     file format elf32-littlearm
    
    SYMBOL TABLE:
    60000000 l    d  .text.headers	00000000 .text.headers
    60001400 l    d  .text.code	00000000 .text.code
    60001e3c l    d  .text.progmem	00000000 .text.progmem
    00000000 l    d  .text.itcm	00000000 .text.itcm
    00002640 l    d  .fini	00000000 .fini
    20000000 l    d  .data	00000000 .data
    20000ec0 l    d  .bss	00000000 .bss
    20200000 l    d  .bss.dma	00000000 .bss.dma
    70000000 l    d  .bss.extram	00000000 .bss.extram
    60005418 l    d  .text.csf	00000000 .text.csf
    00000000 l    d  .debug_info	00000000 .debug_info
    00000000 l    d  .debug_abbrev	00000000 .debug_abbrev
    00000000 l    d  .debug_line	00000000 .debug_line
    00000000 l    d  .debug_frame	00000000 .debug_frame
    00000000 l    d  .debug_str	00000000 .debug_str
    00000000 l    d  .ARM.attributes	00000000 .ARM.attributes
    00000000 l    d  .comment	00000000 .comment
    00000000 l    d  .debug_loclists	00000000 .debug_loclists
    00000000 l    d  .debug_aranges	00000000 .debug_aranges
    00000000 l    d  .debug_rnglists	00000000 .debug_rnglists
    00000000 l    d  .debug_line_str	00000000 .debug_line_str
    00000000 l    df *ABS*	00000000 bootdata.c
    00000000 l    df *ABS*	00000000 startup.c
    60001400 l     F .text.code	00000016 memory_copy
    60001418 l     F .text.code	00000010 memory_clear
    00000000 l    df *ABS*	00000000 tempmon.c
    2000129c l     O .bss	00000004 s_hotCount
    200012a0 l     O .bss	00000004 s_hotTemp
    200012a4 l     O .bss	00000004 s_hot_ROOM
    200012a8 l     O .bss	00000004 s_roomC_hotC
    00000000 l    df *ABS*	00000000 usb.c
    000003dc l     F .text.itcm	00000088 schedule_transfer
    00000464 l     F .text.itcm	00000036 run_callbacks
    0000049c l     F .text.itcm	00000098 endpoint0_transmit.constprop.0
    20001228 l     O .bss	00000008 endpoint0_buffer
    20001230 l     O .bss	00000004 endpoint0_notify_mask
    20001080 l     O .bss	00000008 endpoint0_setupdata
    20001234 l     O .bss	00000004 endpointN_notify_mask
    20001264 l     O .bss	00000008 reply_buffer
    200012e1 l     O .bss	00000001 sof_usage
    200012e8 l     O .bss	00000001 usb_reboot_timer
    00000000 l    df *ABS*	00000000 analog.c
    200012dd l     O .bss	00000001 calibrating
    00000000 l    df *ABS*	00000000 crti.o
    00000000 l    df *ABS*	00000000 crtn.o
    00000000 l    df *ABS*	00000000 crtstuff.c
    00000020 l     F .text.itcm	00000000 register_tm_clones
    00000044 l     F .text.itcm	00000000 frame_dummy
    2000124c l     O .bss	00000000 object.0
    60001e38 l     O .text.code	00000000 __frame_dummy_init_array_entry
    00000000 l    df *ABS*	00000000 usb_desc.c
    200008a8 l     O .data	00000012 device_descriptor
    60001f08 l     O .text.progmem	0000000a qualifier_descriptor
    00000000 l    df *ABS*	00000000 serialEvent.cpp
    00000000 l    df *ABS*	00000000 SymInfo.ino.cpp
    00000000 l    df *ABS*	00000000 delay.c
    00000000 l    df *ABS*	00000000 usb_serial.c
    00000cec l     F .text.itcm	00000060 rx_queue_transfer
    20200060 l     O .bss.dma	00001000 rx_buffer
    00000d4c l     F .text.itcm	000000b4 rx_event
    00000e00 l     F .text.itcm	00000090 usb_serial_flush_callback
    20201060 l     O .bss.dma	00002000 txbuffer
    00000e90 l     F .text.itcm	000001b8 usb_serial_write.part.0
    2000126c l     O .bss	00000004 rx_available
    20001270 l     O .bss	00000010 rx_count
    200012df l     O .bss	00000001 rx_head
    20001280 l     O .bss	00000010 rx_index
    20001290 l     O .bss	00000009 rx_list
    200012d4 l     O .bss	00000002 rx_packet_size
    200012e0 l     O .bss	00000001 rx_tail
    20000f00 l     O .bss	00000100 rx_transfer
    200012e2 l     O .bss	00000001 transmit_previous_timeout
    200012d6 l     O .bss	00000002 tx_available
    200012e3 l     O .bss	00000001 tx_head
    200012e4 l     O .bss	00000001 tx_noautoflush
    200012d8 l     O .bss	00000002 tx_packet_size
    20001000 l     O .bss	00000080 tx_transfer
    00000000 l    df *ABS*	00000000 EventResponder.cpp
    00000000 l    df *ABS*	00000000 Print.cpp
    00000000 l    df *ABS*	00000000 main.cpp
    00000000 l    df *ABS*	00000000 new.cpp
    00000000 l    df *ABS*	00000000 usb_inst.cpp
    00000000 l    df *ABS*	00000000 yield.cpp
    200012dc l     O .bss	00000001 yield::running
    00000000 l    df *ABS*	00000000 memcpy-armv7m.S.o
    00000000 l    df *ABS*	00000000 clockspeed.c
    00000000 l    df *ABS*	00000000 nonstd.c
    00000000 l    df *ABS*	00000000 pwm.c
    00000000 l    df *ABS*	00000000 rtc.c
    00000000 l    df *ABS*	00000000 sm_pool.c
    00000000 l    df *ABS*	00000000 libc_a-malloc.o
    00000000 l    df *ABS*	00000000 libc_a-mallocr.o
    00000000 l    df *ABS*	00000000 libc_a-mlock.o
    00000000 l    df *ABS*	00000000 libc_a-memset.o
    00000000 l    df *ABS*	00000000 libc_a-sbrkr.o
    00000000 l    df *ABS*	00000000 libc_a-errno.o
    00000000 l    df *ABS*	00000000 libc_a-init.o
    00000000 l    df *ABS*	00000000 libc_a-lock.o
    00000000 l    df *ABS*	00000000 libc_a-freer.o
    00000000 l    df *ABS*	00000000 libc_a-impure.o
    00000000 l    df *ABS*	00000000 HardwareSerial.cpp
    60001df8 l     F .text.code	00000008 __main_veneer
    60001e00 l     F .text.code	00000008 __usb_init_serialnumber_veneer
    60001e08 l     F .text.code	00000008 __pwm_init_veneer
    60001e10 l     F .text.code	00000008 __sm_set_pool_veneer
    60001e18 l     F .text.code	00000008 ____libc_init_array_veneer
    60001e20 l     F .text.code	00000008 __delay_veneer
    60001e28 l     F .text.code	00000008 __set_arm_clock_veneer
    60001e30 l     F .text.code	00000008 __memset_veneer
    00002628 l     F .text.itcm	00000008 ___init_veneer
    00002630 l     F .text.itcm	00000008 ___reboot_Teensyduino__veneer
    0000125c g     F .text.itcm	00000018 usb_serial_available
    60001650 g     F .text.code	00000002 startup_default_late_hook
    000014ec  w    F .text.itcm	000000f0 yield
    200012d0 g     O .bss	00000004 usb_timer1_callback
    60001e54 g     O .text.progmem	00000018 usb_string_manufacturer_name_default
    6000174c g     F .text.code	00000384 configure_external_ram
    0000149c g     F .text.itcm	0000001c Print::println()
    00002248 g     F .text.itcm	0000000c __malloc_unlock
    60001d98 g     F .text.code	00000054 analog_init
    2000047c g     O .data	00000004 F_CPU_ACTUAL
    00002644 g       .data	00000000 __exidx_end
    200012da g     O .bss	00000001 EventResponder::runningFromYield
    0000037c g     F .text.itcm	00000060 tempmonGetTemp
    0000231c g     F .text.itcm	0000000c __errno
    60001000 g     O .text.headers	00000020 ImageVectorTable
    20001090 g     O .bss	00000004 EventResponder::firstInterrupt
    00000c90 g     F .text.itcm	00000004 usb_transfer_status
    00001c44 g     F .text.itcm	00000084 sm_set_pool
    000014e4  w    F .text.itcm	00000008 usb_serial_class::write(unsigned char const*, unsigned int)
    20001238 g     O .bss	00000004 errno
    00002640 g       .text.itcm	00000000 _etext
    20000ec0 g       .bss	00000000 _sbss
    60001f14 g       *ABS*	00000000 _stextload
    00000118 g     F .text.itcm	00000002 loop
    00001a64 g     F .text.itcm	0000007a flexpwm_init
    00000b54 g     F .text.itcm	00000064 usb_config_rx
    2000108c g     O .bss	00000004 EventResponder::lastInterrupt
    000015dc g     F .text.itcm	00000134 memcpy
    20000ec0 g     O .data	00000000 .hidden __TMC_END__
    200012b4 g     O .bss	00000004 systick_millis_count
    200012e6 g     O .bss	00000001 usb_configuration
    00001bf8 g     F .text.itcm	0000004c sm_align_pool
    60000000 g     O .text.headers	00000200 FlexSPI_NOR_Config
    60001e54  w    O .text.progmem	00000018 usb_string_manufacturer_name
    00001ccc g     F .text.itcm	00000010 malloc
    60001c5c g     F .text.code	000000e8 usb_init
    200010ec g     O .bss	00000004 __malloc_top_pad
    200012b8 g     O .bss	00000004 systick_safe_read
    aaaaaaab g       *ABS*	00000000 _flexram_bank_config
    20000000 g       .data	00000000 _sdata
    60001ebc g     O .text.progmem	0000004b usb_config_descriptor_480
    000022f8 g     F .text.itcm	00000024 _sbrk_r
    60001648 g     F .text.code	00000002 startup_default_early_hook
    60001428 g     F .text.code	00000220 ResetHandler
    000012e4 g     F .text.itcm	00000020 usb_serial_getchar
    200012c0 g     O .bss	00000008 usb_cdc_line_coding
    20001094 g     O .bss	00000004 EventResponder::lastYield
    2000123c g     O .bss	00000010 extmem_smalloc_pool
    200010e4 g     O .bss	00000004 __malloc_max_sbrked_mem
    200012bc g     O .bss	00000004 test_struct_ptr
    60005800 g     O .text.csf	00000c00 hab_csf
    20280000 g       .text.csf	00000000 _heap_end
    00002644 g       .data	00000000 __exidx_start
    70000000 g       .bss.extram	00000000 _extram_end
    20001088 g     O .bss	00000004 EventResponder::firstYield
    00002328 g     F .text.itcm	00000048 __libc_init_array
    000014cc  w    F .text.itcm	00000004 usb_serial_class::clear()
    00000344 g     F .text.itcm	00000034 _sbrk
    60004558 g       *ABS*	00000000 _sdataload
    20000490 g     O .data	00000004 __brkval
    200012e5 g     O .bss	00000001 usb_cdc_line_rtsdtr
    60001dec g     F .text.code	00000000 _init
    00001048 g     F .text.itcm	00000002 usb_serial_reset
    60001e70 g     O .text.progmem	0000004b usb_config_descriptor_12
    20001320 g       .bss	00000000 _ebss
    20203060 g       .bss.dma	00000000 _heap_start
    200010b8 g     O .bss	00000001 __lock___malloc_recursive_mutex
    200010f0 g     O .bss	00000138 __sf
    00000001 g       *ABS*	00000000 _itcm_block_count
    20000ee0 g     O .bss	00000020 endpoint0_transfer_data
    00001ae0 g     F .text.itcm	000000f4 pwm_init
    60006400 g       .text.csf	00000000 __text_csf_end
    60001ad0 g     F .text.code	0000005c usb_pll_start
    20000ec0 g     O .bss	00000020 endpoint0_transfer_ack
    200012c8 g     O .bss	00000004 usb_cdc_line_rtsdtr_millis
    00000c4c g     F .text.itcm	00000028 usb_transmit
    00001474 g     F .text.itcm	00000020 systick_isr
    00002374 g     F .text.itcm	00000002 __retarget_lock_release_recursive
    20000480 g     O .data	00000010 Serial
    00001494  w    F .text.itcm	00000006 usb_serial_class::write(unsigned char)
    60001648  w    F .text.code	00000002 startup_early_hook
    00001218 g     F .text.itcm	00000044 usb_serial_peekchar
    00001710 g     F .text.itcm	000002f0 set_arm_clock
    200012b0 g     O .bss	00000004 systick_cycle_count
    200008bc g     O .data	00000016 usb_string_serial_number_default
    00002418 g     F .text.itcm	0000020c _free_r
    000014dc  w    F .text.itcm	00000004 usb_serial_class::flush()
    2000089c g     O .data	00000004 __malloc_sbrk_base
    000014d4  w    F .text.itcm	00000004 usb_serial_class::read()
    00000c1c g     F .text.itcm	00000030 usb_prepare_transfer
    000001c4 g     F .text.itcm	00000180 unused_interrupt_vector
    200012cc g     O .bss	00000004 usb_timer0_callback
    60001b2c g     F .text.code	00000130 tempmon_init
    00001cc8  w    F .text.itcm	00000002 serialEvent()
    00001274 g     F .text.itcm	00000070 usb_serial_flush_input
    00001304 g     F .text.itcm	0000002c usb_serial_putchar
    00000025 g       *ABS*	00000000 _teensy_model_identifier
    200010bc g     O .bss	00000028 __malloc_current_mallinfo
    20001098 g     O .bss	00000020 HardwareSerial::s_serials_with_serial_events
    60001d44 g     F .text.code	00000054 _reboot_Teensyduino_
    6000164c g     F .text.code	00000002 startup_default_middle_hook
    00000560 g     F .text.itcm	000005f4 usb_isr
    20000280  w    O .data	00000028 vtable for usb_serial_class
    200012ac g     O .bss	00000004 scale_cpu_cycles_to_microseconds
    20000494 g     O .data	00000408 __malloc_av_
    00001398 g     F .text.itcm	00000094 usb_serial_flush_output
    0000223c g     F .text.itcm	0000000c __malloc_lock
    20000c00 g     O .data	000002c0 _VectorsRam
    200008d2 g     O .data	00000001 yield_active_check_flags
    00002370 g     F .text.itcm	00000002 __retarget_lock_acquire_recursive
    200012e7 g     O .bss	00000001 usb_high_speed
    00002254 g     F .text.itcm	000000a4 memset
    000014b8 g     F .text.itcm	00000010 main
    200010e8 g     O .bss	00000004 __malloc_max_total_mem
    20200000 g     O .bss.dma	0000004b usb_descriptor_buffer
    00000c94 g     F .text.itcm	00000058 usb_init_serialnumber
    60001e3c g       .text.code	00000000 __init_array_end
    00001cdc g     F .text.itcm	00000560 _malloc_r
    200012db g     O .bss	00000001 HardwareSerial::s_count_serials_with_serial_events
    00002378 g     F .text.itcm	000000a0 _malloc_trim_r
    60001e6c g     O .text.progmem	00000004 string0
    00001330 g     F .text.itcm	00000018 usb_serial_write
    60001650  w    F .text.code	00000002 startup_late_hook
    000014d8  w    F .text.itcm	00000004 usb_serial_class::available()
    60001f12 g     O .text.progmem	00000001 _serialEvent_default
    20000000 g     O .data	00000280 endpoint_queue_head
    60001e3c  w    O .text.progmem	00000016 usb_string_product_name
    0000011c g     F .text.itcm	000000a8 delay
    00002640 g     F .fini	00000000 _fini
    60001020 g     O .text.headers	0000000c BootData
    00000378 g     F .text.itcm	00000004 Panic_Temp_isr
    200008a4 g     O .data	00000004 _impure_ptr
    60001e38 g       .text.code	00000000 __preinit_array_end
    00000534 g     F .text.itcm	0000002c usb_stop_sof_interrupts
    00000068 g     F .text.itcm	000000b0 setup
    200002ec g     O .data	0000006c usb_descriptor_list
    20078000 g       .text.csf	00000000 _estack
    00001348 g     F .text.itcm	00000050 usb_serial_write_buffer_free
    0000104c g     F .text.itcm	000000ec usb_serial_configure
    20000ec0 g       .data	00000000 _edata
    200012de g     O .bss	00000001 external_psram_size
    000014e0  w    F .text.itcm	00000004 usb_serial_class::availableForWrite()
    00001a00 g     F .text.itcm	00000062 ultoa
    000014c8 g     F .text.itcm	00000004 operator new(unsigned int)
    0000142c g     F .text.itcm	00000044 EventResponder::runFromInterrupt()
    200008a0 g     O .data	00000004 __malloc_trim_threshold
    000014d0  w    F .text.itcm	00000004 usb_serial_class::peek()
    20000358 g     O .data	00000120 _impure_data
    60001e38 g       .text.code	00000000 __init_array_start
    20000478 g     O .data	00000004 F_BUS_ACTUAL
    00000000 g       .text.itcm	00000000 _stext
    60001e3c g     O .text.progmem	00000016 usb_string_product_name_default
    6000164c  w    F .text.code	00000002 startup_middle_hook
    60001654 g     F .text.code	000000f8 configure_cache
    60001e38 g       .text.code	00000000 __preinit_array_start
    00000c74 g     F .text.itcm	0000001c usb_receive
    00006400 g       *ABS*	00000000 _flashimagelen
    00001bd4 g     F .text.itcm	00000024 rtc_get
    70000000 g       .bss.extram	00000000 _extram_start
    00001470 g     F .text.itcm	00000004 pendablesrvreq_isr
    00001138 g     F .text.itcm	000000e0 usb_serial_read
    00000bb8 g     F .text.itcm	00000064 usb_config_tx
    200008bc  w    O .data	00000016 usb_string_serial_number

  4. #4
    Hey! Thanks for that detailed response! I already spent some time on the memory-section of the Teensy page, because in the last 25years of earning money with programming, I never needed to care how compilers use memory. Those few projects that were not in languages that did all the memory management for me were small enough to ignore that and focus more on getting the manual memory management right, and even in the late 90th, while working on quite big web applications, it was easy enough to put a few more boxes into the racks, or upgrade RAM :P
    Maybe I start learning about that, now that I seem to need that...

    I spent some time this morning playing around with an empty sketch, trying to get a feel of how much memory code takes up, and besides realizing that even those few libraries I use (one for the OLED display and the USBHost_t3) take up quite some kilobytes of ram with variables and code, so comparing the amount of source code in my project to those libs it seems okay.

    will play around more to find ways to reduce the 340k code that is placed in RAM1.
    It feels as if most functions now have a FLASHMEM and still code takes up nearly as much space in RAM1 than in FLASH

    Code:
    teensy_size: Memory Usage on Teensy 4.1:
    teensy_size:   FLASH: code:461108, data:54892, headers:8924   free for files:7601540
    teensy_size:    RAM1: variables:130144, code:336144, padding:24304   free for local variables:33696
    teensy_size:    RAM2: variables:7200  free for malloc/new:517088
    Last edited by Uija; 03-05-2023 at 05:50 AM. Reason: Removed paragraph, because I did something wrong

  5. #5
    Is the issue that you put YOUR code in FLASHMEM so that it is not copied to FastRun but the libraries still get copied to FastRun?

  6. #6
    I tested it in an empty sketch and it seems, that the libraries take up maybe 30-40k of the 334k memory that is used, so I would be more than fine, if I get my code out there :P

  7. #7
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    17,137
    Have fun. p#4 padding shows the next 8K of code out of RAM1 ITCM almost doubles the 33KB of free space for DATA DTCM giving another 32KB.

    ... then it is on to the next 32KB of code to remove ...

    Perhaps the SMALLEST CODE build would help and not hurt speed too much ... as least it may free more code space to build and run.

  8. #8
    I am not 100% sure why it freed up so much RAM, but YAY!

    Code:
    teensy_size: Memory Usage on Teensy 4.1:
    teensy_size:   FLASH: code:372928, data:55916, headers:9040   free for files:7688580
    teensy_size:    RAM1: variables:74208, code:243152, padding:18992   free for local variables:187936
    teensy_size:    RAM2: variables:47616  free for malloc/new:476672
    I have a 15 byte big struct, that contains the intervals and a name of chords, I have 27 of them, I moved them from being const and directly initialized to static and being initialized in a method.

    Old:

    Code:
        #define NUM_CHORDS 27
        struct Chord {
            char chord_name[8];
            int8_t chord_intervals[NUM_CHORDS_INTERVALS];
            Chord( const __FlashStringHelper* name, int8_t i1, int8_t i2, int8_t i3, int8_t i4, int8_t i5, int8_t i6, int8_t i7) : chord_intervals{i1, i2, i3, i4, i5, i6, i7} {memset( chord_name, 0, 8); strncpy( chord_name, (const char*)name, 7);}
        };
        const Chord MODIFIER_CHORDS[NUM_CHORDS] = {
            {F("-"), 0, 100, 100, 100, 100, 100, 100},
            {F("maj"), 0, 4, 7, 100, 100, 100, 100},
            ...
        };
    I already tried to make it smaller by passing FlashLocated Strings into the constructor, but if I remember correctly, it didn't help...

    I changed it to:

    Code:
        #define NUM_CHORDS 27
        struct Chord {
            char chord_name[8];
            int8_t chord_intervals[NUM_CHORDS_INTERVALS];
            Chord( const __FlashStringHelper* name, int8_t i1, int8_t i2, int8_t i3, int8_t i4, int8_t i5, int8_t i6, int8_t i7) : chord_intervals{i1, i2, i3, i4, i5, i6, i7} {memset( chord_name, 0, 8); strncpy( chord_name, (const char*)name, 7);}
        };
    
         static Chord MODIFIER_CHORDS[NUM_CHORDS];
    
        void prepareGlobalData() {
            MODIFIER_CHORDS[0] = {F("-"), 0, 100, 100, 100, 100, 100, 100};
            MODIFIER_CHORDS[1] = {F("maj"), 0, 4, 7, 100, 100, 100, 100};
            ...
            MODIFIER_CHORDS[26] = {F("add11"), 0, 4, 7, 17, 100, 100, 100};
        }
    I call this method from my setup(). Memory usage moved from

    RAM1: variables:130144, code:336144, padding:24304 free for local variables:33696

    to

    teensy_size: RAM1: variables:114592, code:243152, padding:18992 free for local variables:147552

    Thats ~15kbyte variables and ~90kbyte code. Why? 27*(7+8) = 405bytes

    I See, I have a hell lot to learn :P
    By moving the Array to DMAMEM and the prepareGlobalData to FLASHMEM I ended with:

    RAM1: variables:74208, code:243152, padding:18992 free for local variables:187936

  9. #9
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    17,137
    That's a huge difference from some attention to details

  10. #10
    Quote Originally Posted by Uija View Post
    Thats ~15kbyte variables and ~90kbyte code. Why? 27*(7+8) = 405bytes
    My guess is that if they are consts then the compiler treated them like #defines, rather than putting a single copy somewhere and pointing to it each time you used the values it duplicated the values every time they were used. This saves an extra step of indirection every access and so gives a speed increase at the cost of code size.
    By making them static you are forcing the compiler to only have one copy and refer back to it each time. Slower but a far smaller memory footprint.

  11. #11
    Senior Member
    Join Date
    Feb 2018
    Location
    Corvallis, OR
    Posts
    440
    I find the following code a bit confusing:
    Code:
        struct Chord {
            char chord_name[8];
            int8_t chord_intervals[NUM_CHORDS_INTERVALS];
            Chord( const __FlashStringHelper* name, int8_t i1, int8_t i2, int8_t i3, int8_t i4, int8_t i5, int8_t i6, int8_t i7) : chord_intervals{i1, i2, i3, i4, i5, i6, i7}\
                         {memset( chord_name, 0, 8); strncpy( chord_name, (const char*)name, 7);}
        };
    It looks as if you are defining a Chord struct which has as one of its elements a Chord struct. That brings back recursion nightmares--which could probably be solved by changing the name of the structure element to "ChordData".

    It would probably be helpful to do:
    Serial.printf("Chord Struct size: %lu, Chord Array Size: %lu\n", sizeof(Chord), sizeof(Chords)).

    I suspect that you will find that the array size is not numchords * sizeof(Chord), since the array elements will be padded out to either 16 or 32 bits. The padding may also occur in the struct definition where the individual byte elements may be padded to 16 or 32 bits so that the CPU doesn't have to access odd addresses for individual items.

  12. #12
    Where do you find that that nested Chord struct. maybe I am blind, but I see a struct with a Constructor there, or am I understanding that wrong?

  13. #13
    Senior Member
    Join Date
    Feb 2018
    Location
    Corvallis, OR
    Posts
    440
    Quote Originally Posted by Uija View Post
    Where do you find that that nested Chord struct. maybe I am blind, but I see a struct with a Constructor there, or am I understanding that wrong?
    I'm not that familiar with the nuances of the current C++ usage of constructors. It may be perfectly legitimate to include a constructor inside a struct definition.

    I have made my peace with an alternate way to initialize the elements of a struct:

    struct foo {
    bool a = true;
    bool b = true;
    bool c;
    } bar;

    which does not require a constructor.

Posting Permissions

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