Other Parts Discussed in Thread: SEGGER
Tool/software:
Hello there
I implemented an emulated eeprom based on TI's application note which is working fine. In the linker file I reserved a memory area for the emulated eeprom. Since the lower 32kB flash address space supports higher erase/program endurance, I placed the emulated eeprom at the flash base address (0x0000.0000) and the main program at the flash address 0x0000.1400 This was working fine, when the debugger was connected. Without a debugger connected, the main program wouldn't start.
After a bit of research I found out, that the settings of the debugger or to be precise the debugging software (SEGGER Ozone) handles the the relocating of the vector table and sets the program counter correctly.
To fix that, I added a memory area with a bootloader stump that contains a small vector table with a stack pointer and a reset handler. This reset hander than executes the jump to the main applications reset handler. This is working as expected. As much as I understand, the controller by defaults expects a vector table at the flash base address with a stack pointer and a reset handler.
Since the emulated eeprom start address needs to be at a page address, I reserved a whole flash page for the bootloader stump although it wouldn't need as much flash memory.
I would rather not have a additional memory section only for the bootloader stump with its own boot vector table but only have the main vector table based at the address 0x0000.0000. is there any other solution then the one I'm using at the moment? Can I somehow split my main program between two non consecutive flash areas?
My linker file:
/* Generate a link error if heap and stack don't fit into RAM */ _Min_Heap_Size = 0; /* required amount of heap */ _Min_Stack_Size = 0x80; /* required amount of stack */ /* Specify the memory areas */ MEMORY { FLASH_BOOT (RX) : ORIGIN = 0x00000000, LENGTH = 1K EMULATED_EEPROM (RW) : ORIGIN = 0x00000400, LENGTH = 4K FLASH (RX) : ORIGIN = 0x00001400, LENGTH = 123K SRAM (RWX) : ORIGIN = 0x20200000, LENGTH = 32K BCR_CONFIG (R) : ORIGIN = 0x41C00000, LENGTH = 0x00000080 BSL_CONFIG (R) : ORIGIN = 0x41C00100, LENGTH = 0x00000080 } /* Note: SRAM length must match MPPC/MEMSS config! Please edit it manually. */ REGION_ALIAS("REGION_TEXT", FLASH); REGION_ALIAS("REGION_PREINIT_ARRAY", FLASH); REGION_ALIAS("REGION_INIT_ARRAY", FLASH); REGION_ALIAS("REGION_FINI_ARRAY", FLASH); REGION_ALIAS("REGION_BSS", SRAM); REGION_ALIAS("REGION_NOINIT", SRAM); REGION_ALIAS("REGION_DATA", SRAM); REGION_ALIAS("REGION_STACK", SRAM); REGION_ALIAS("REGION_HEAP", SRAM); REGION_ALIAS("REGION_TEXT_RAM", SRAM); REGION_ALIAS("REGION_ARM_EXIDX", FLASH); REGION_ALIAS("REGION_ARM_EXTAB", FLASH); /* Define output sections */ SECTIONS { /* section for the boot interrupt vector area */ PROVIDE (_intvecs_boot_base_address = DEFINED(_intvecs_boot_base_address) ? _intvecs_boot_base_address : 0x00000000); .intvecs_boot (_intvecs_boot_base_address) : AT (_intvecs_boot_base_address) { . = ALIGN(0x4); KEEP (*(.intvecs_boot)) . = ALIGN(0x4); } > FLASH_BOOT __emulated_eeprom_base_address = ORIGIN(EMULATED_EEPROM); .emulated_eeprom : { . = ALIGN(0x8); KEEP (*(.emulated_eeprom)) . = ALIGN(0x8); } > EMULATED_EEPROM __program_base_address = ORIGIN(FLASH); /* section for the interrupt vector area */ PROVIDE (_intvecs_base_address = DEFINED(_intvecs_base_address) ? _intvecs_base_address : __program_base_address); .intvecs (_intvecs_base_address) : AT (_intvecs_base_address) { KEEP (*(.intvecs)) } > REGION_TEXT PROVIDE (_vtable_base_address = DEFINED(_vtable_base_address) ? _vtable_base_address : 0x20200000); .vtable (_vtable_base_address) : AT (_vtable_base_address) { KEEP (*(.vtable)) } > REGION_DATA .text : { CREATE_OBJECT_SYMBOLS KEEP (*(.text)) . = ALIGN(0x8); *(.text.*) . = ALIGN(0x8); KEEP (*(.ctors)) . = ALIGN(0x8); KEEP (*(.dtors)) . = ALIGN(0x8); KEEP (*(.init)) . = ALIGN(0x8); KEEP (*(.fini*)) . = ALIGN(0x8); } > REGION_TEXT AT> REGION_TEXT .ramfunc : { __ramfunct_load__ = LOADADDR (.ramfunc); __ramfunct_start__ = .; *(.ramfunc) . = ALIGN(0x8); __ramfunct_end__ = .; } > REGION_TEXT_RAM AT> REGION_TEXT .rodata : { *(.rodata) . = ALIGN(0x8); *(.rodata.*) . = ALIGN(0x8); } > REGION_TEXT AT> REGION_TEXT .preinit_array : { PROVIDE_HIDDEN (__preinit_array_start = .); KEEP (*(.preinit_array*)); PROVIDE_HIDDEN (__preinit_array_end = .); } > REGION_PREINIT_ARRAY AT> REGION_TEXT .init_array : { . = ALIGN(0x8); PROVIDE_HIDDEN (__init_array_start = .); KEEP (*(SORT(.init_array.*))) KEEP (*(.init_array*)) PROVIDE_HIDDEN (__init_array_end = .); } > REGION_INIT_ARRAY AT> REGION_TEXT .fini_array : { . = ALIGN(0x8); PROVIDE_HIDDEN (__fini_array_start = .); KEEP (*(SORT(.fini_array.*))) KEEP (*(.fini_array*)) PROVIDE_HIDDEN (__fini_array_end = .); } > REGION_FINI_ARRAY AT> REGION_TEXT .ARM.exidx : { . = ALIGN(0x8); __exidx_start = .; *(.ARM.exidx* .gnu.linkonce.armexidx.*) . = ALIGN(0x8); __exidx_end = .; } > REGION_ARM_EXIDX AT> REGION_ARM_EXIDX .ARM.extab : { KEEP (*(.ARM.extab* .gnu.linkonce.armextab.*)) . = ALIGN(0x8); } > REGION_ARM_EXTAB AT> REGION_ARM_EXTAB __etext = .; .data : { __data_load__ = LOADADDR (.data); __data_start__ = .; KEEP (*(.data)) KEEP (*(.data*)) . = ALIGN (8); __data_end__ = .; } > REGION_DATA AT> REGION_TEXT .bss : { __bss_start__ = .; *(.shbss) KEEP (*(.bss)) *(.bss.*) *(COMMON) . = ALIGN (8); __bss_end__ = .; } > REGION_BSS AT> REGION_BSS .noinit : { /* place all symbols in input sections that start with .noinit */ KEEP(*(*.noinit*)) . = ALIGN (8); } > REGION_NOINIT AT> REGION_NOINIT .heap : { __heap_start__ = .; end = __heap_start__; _end = end; __end = end; KEEP (*(.heap)) __heap_end__ = .; __HeapLimit = __heap_end__; } > REGION_HEAP AT> REGION_HEAP .stack (NOLOAD) : ALIGN(0x8) { _stack = .; KEEP(*(.stack)) } > REGION_STACK AT> REGION_STACK .BCRConfig : { KEEP(*(.BCRConfig)) } > BCR_CONFIG .BSLConfig : { KEEP(*(.BSLConfig)) } > BSL_CONFIG __StackTop = ORIGIN(REGION_STACK) + LENGTH(REGION_STACK); PROVIDE(__stack = __StackTop); }