john_c_kennedy
Active member
Is it possible to boot from the SD card?
Has anyone done this?
Does anyone know how to make this work?
Thanks,
John
Has anyone done this?
Does anyone know how to make this work?
Thanks,
John
Is it possible to boot from the SD card?
Has anyone done this?
Does anyone know how to make this work?
Thanks,
John
All the code on the Teensy 4/4.1 is running from RAM by default. There's a big thread about how exactly the RAM sections on the IMXRT1062 work here: https://forum.pjrc.com/threads/57326-T4-0-Memory-trying-to-make-sense-of-the-different-regions
.text.itcm : {
. = . + 32; /* MPU to trap NULL pointer deref */
*(.fastrun)
*(.text*)
. = ALIGN(16);
} > ITCM AT> FLASH
According to the docs:
https://www.pjrc.com/store/teensy40.html
it is indeed copied to RAM.
-Michael
Can anyone at PJRC clairify this issue
i.e. does the bootloader relocate the code and copy it to RAM for execution?
Also I'd still be interested in how much faster code in RAM is compared to FLASH?
From https://github.com/PaulStoffregen/cores/blob/master/teensy4/imxrt1062.ldCode:.text.itcm : { . = . + 32; /* MPU to trap NULL pointer deref */ *(.fastrun) *(.text*) . = ALIGN(16); } > ITCM AT> FLASH
I only glanced at the article you linked, but it sounded like they were using a custom link script and not the default Teensyduino one, in which case they could have been running from flash.
Thanks Paul for clearing this up, very helpful. I'm not currently trying to do anything special with memory, just trying to understand how all this works. It looks to me like the linker script puts .text.progmem in flash and text.itcm in itcm ram. How does the compiler assign these attributes to the code without an explicit attribute in the source code itself?
John
By default, or when FASTRUN is used on functions, they are compiled to run from ITCM and loaded into that section of the flash which gets copied to ITCM at startup.
But not all code runs from ITCM. Functions with FLASHMEM are located only in the flash memory and "execute in place" from the flash. Normally only startup code has FLASHMEM on its functions, since the flash is so much slower in the case of a cache miss. But the M7 processor does have 32K of L1 cache just for instructions, and also 32K of L1 cache for data, so executing from flash isn't always as bad as you might imagine.
So the answer is more complicated than all code running from one type of memory. Most functions run from ITCM, but those declared with FLASHMEM do indeed execute in place directly from flash memory.
MEMORY
{
ITCM (rwx): ORIGIN = 0x00000000, LENGTH = 512K
DTCM (rwx): ORIGIN = 0x20000000, LENGTH = 512K
RAM (rwx): ORIGIN = 0x20200000, LENGTH = 512K
FLASH (rwx): ORIGIN = 0x60000000, LENGTH = 7936K
ERAM (rwx): ORIGIN = 0x70000000, LENGTH = 16384K
}
ENTRY(ImageVectorTable)
SECTIONS
{
.text.progmem : {
KEEP(*(.flashconfig))
FILL(0xFF)
. = ORIGIN(FLASH) + 0x1000;
KEEP(*(.ivt))
KEEP(*(.bootdata))
KEEP(*(.vectors))
KEEP(*(.startup))
*(.flashmem*)
*(.progmem*)
. = ALIGN(4);
KEEP(*(.init))
__preinit_array_start = .;
KEEP (*(.preinit_array))
__preinit_array_end = .;
__init_array_start = .;
KEEP (*(.init_array))
__init_array_end = .;
. = ALIGN(16);
} > FLASH
.text.itcm : {
. = . + 32; /* MPU to trap NULL pointer deref */
*(.fastrun)
*(.text*)
. = ALIGN(16);
} > ITCM AT> FLASH
.text.itcm.padding (NOLOAD) : {
. = ALIGN(32768);
} > ITCM
.data : {
*(.rodata*)
*(.data*)
. = ALIGN(16);
} > DTCM AT> FLASH
.bss ALIGN(4) : {
*(.bss*)
*(COMMON)
. = ALIGN(32);
. = . + 32; /* MPU to trap stack overflow */
} > DTCM
.bss.dma (NOLOAD) : {
*(.dmabuffers)
. = ALIGN(32);
} > RAM
.bss.extram (NOLOAD) : {
*(.externalram)
} > ERAM
_stext = ADDR(.text.itcm);
_etext = ADDR(.text.itcm) + SIZEOF(.text.itcm);
_stextload = LOADADDR(.text.itcm);
_sdata = ADDR(.data);
_edata = ADDR(.data) + SIZEOF(.data);
_sdataload = LOADADDR(.data);
_sbss = ADDR(.bss);
_ebss = ADDR(.bss) + SIZEOF(.bss);
_heap_start = ADDR(.bss.dma) + SIZEOF(.bss.dma);
_heap_end = ORIGIN(RAM) + LENGTH(RAM);
_itcm_block_count = (SIZEOF(.text.itcm) + 0x7FFF) >> 15;
_flexram_bank_config = 0xAAAAAAAA | ((1 << (_itcm_block_count * 2)) - 1);
_estack = ORIGIN(DTCM) + ((16 - _itcm_block_count) << 15);
_flashimagelen = SIZEOF(.text.progmem) + SIZEOF(.text.itcm) + SIZEOF(.data);
_teensy_model_identifier = 0x25;
.debug_info 0 : { *(.debug_info) }
.debug_abbrev 0 : { *(.debug_abbrev) }
.debug_line 0 : { *(.debug_line) }
.debug_frame 0 : { *(.debug_frame) }
.debug_str 0 : { *(.debug_str) }
.debug_loc 0 : { *(.debug_loc) }
}
#define DMAMEM __attribute__ ((section(".dmabuffers"), used))
#define FASTRUN __attribute__ ((section(".fastrun") ))
#define PROGMEM __attribute__((section(".progmem")))
#define FLASHMEM __attribute__((section(".flashmem")))
#define EXTMEM __attribute__((section(".externalram")))
Thanks Michael, I think I understand now, in the .text.itcm section it includes everything with the .fastrun attribute and everything with the .text* attributes. So I assume the compiler assigns a .text attribute by default to any code that doesn't have another attribute assigned otherwise. I was confused by the section names .text.progmem and .text.itcm, which are just the section names and not what goes in them, what parts of the code that go in each section is specified in the body of the section declaration between the {}. Sorry for my denseness. Perhaps you guys should write a book "Teensy for Dummy's" or some such for such as I. Thanks again for your patient and detailed reply, much appreciated.
John
int zero (void) { return 0; }
Perhaps you guys should write a book "Teensy for Dummy's" or some such for such as I.
We do indeed need much more beginner-oriented tutorial material.
I'd be glad to help if I can.
But diving into the details of linker scripts isn't quite what I would have in mind for topics to cover in such tutorials...