[ECOS] small custom bootloader to start an app stored in flash

Rainer Arndt arndt@ibehs.de
Wed Oct 22 19:01:00 GMT 2014


Am 22. Oktober 2014 13:08:33 MESZ, schrieb Oleg Uzenkov <o.uzenkov@unicore.co.ua>:
>Thanks,
>>> Any ideas how to make a jump to start an app? May be some sample
>code
>>> showing how to do it in eCos? May be someone has done it already?
>> // Make a function pointer and assigned it to the address you want to
>jump to.
>> void (*startApp1)(void) = 0x08002000 ;
>>
>> // Disable the interrupts.
>> cyg_interrupt_disable();
>>
>> //Call the function.
>> startApp1();
>I have tried it but could not get it working yet (stm32f4-discovery
>board).
>
>May be I am missing something in the understanding of the principles.
>
>Please could you check.
>
>1. Here is the code of my bootloader:
>
>...
>static void (*startApp)(void) = ( void(*)(void) ) (0x08020000) ;
>
>int main (void) {
>
>   diag_printf( "IN JUMP\n" );
>
>   cyg_interrupt_disable();
>
>   startApp();
>
>   while (1);
>
>   return 0;
>}
>
>I build it with ROM startup and flash at 0x08000000
>
>mlt files:
>
>*.ldi:
>
>MEMORY
>{
>     ram   : ORIGIN = 0x20000000, LENGTH = 
>0x00020000-CYGNUM_HAL_COMMON_INTERRUPTS_STACK_SIZE
>     flash : ORIGIN = 0x08000000, LENGTH = 0x00100000
>     ccm   : ORIGIN = 0x10000000, LENGTH = 0x00010000
>}
>
>hal_vsr_table = 0x20000000;
>hal_virtual_vector_table = hal_vsr_table + 98*4;
>#if defined(CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT)
>hal_virtual_vector_table_end = hal_virtual_vector_table + 64*4;
>#else // zero size virtual vector table
>hal_virtual_vector_table_end = hal_virtual_vector_table;
>#endif
>
>// SRAM is 128k.
>hal_startup_stack = 0x20000000 + 1024*128;
>
>SECTIONS
>{
>     SECTIONS_BEGIN
>     USER_SECTION (ccm, ccm, 0x10000000 (NOLOAD), LMA_EQ_VMA)
>     SECTION_rom_vectors (flash, 0x08000000, LMA_EQ_VMA)
>     SECTION_RELOCS (flash, ALIGN (0x8), LMA_EQ_VMA)
>     SECTION_text (flash, ALIGN (0x8), LMA_EQ_VMA)
>     SECTION_fini (flash, ALIGN (0x8), LMA_EQ_VMA)
>     SECTION_rodata (flash, ALIGN (0x8), LMA_EQ_VMA)
>     SECTION_rodata1 (flash, ALIGN (0x8), LMA_EQ_VMA)
>     SECTION_fixup (flash, ALIGN (0x8), LMA_EQ_VMA)
>     SECTION_gcc_except_table (flash, ALIGN (0x8), LMA_EQ_VMA)
>     SECTION_eh_frame (flash, ALIGN (0x8), LMA_EQ_VMA)
>     SECTION_got (flash, ALIGN (0x8), LMA_EQ_VMA)
>     SECTION_sram (ram, hal_virtual_vector_table_end, FOLLOWING (.got))
>     SECTION_data (ram, ALIGN( 0x8), FOLLOWING (.sram))
>     SECTION_bss (ram, ALIGN (0x8), LMA_EQ_VMA)
>     CYG_LABEL_DEFN(__heap1) = ALIGN (0x8);
>     SECTIONS_END
>}
>
>*.h:
>#define CYGMEM_REGION_ram (0x20000000)
>#define CYGMEM_REGION_ram_SIZE 
>(0x00020000-CYGNUM_HAL_COMMON_INTERRUPTS_STACK_SIZE)
>#define CYGMEM_REGION_ram_ATTR (CYGMEM_REGION_ATTR_R |
>CYGMEM_REGION_ATTR_W)
>#define CYGMEM_REGION_ccm (0x10000000)
>#define CYGMEM_REGION_ccm_SIZE (0x00010000)
>#define CYGMEM_REGION_ccm_ATTR (CYGMEM_REGION_ATTR_R |
>CYGMEM_REGION_ATTR_W)
>#define CYGMEM_REGION_flash (0x08000000)
>#define CYGMEM_REGION_flash_SIZE (0x00100000)
>#define CYGMEM_REGION_flash_ATTR (CYGMEM_REGION_ATTR_R | 
>CYGMEM_REGION_ATTR_W)
>#ifndef __ASSEMBLER__
>extern char CYG_LABEL_NAME (__heap1) [];
>#endif
>#define CYGMEM_SECTION_heap1 (CYG_LABEL_NAME (__heap1))
>#define CYGMEM_SECTION_heap1_SIZE 
>(CYGMEM_REGION_ram+CYGMEM_REGION_ram_SIZE - (size_t) CYG_LABEL_NAME 
>(__heap1))
>
>2. Here is the code of my app to which I want to jump to:
>
>int main (void) {
>
>   diag_printf( "IN APP\n" );
>
>   while (1);
>
>   return 0;
>}
>
>I build it with ROM startup and flash it at 0x08020000
>
>mlt files:
>
>*.ldi:
>
>MEMORY
>{
>     ram   : ORIGIN = 0x20000000, LENGTH = 
>0x00020000-CYGNUM_HAL_COMMON_INTERRUPTS_STACK_SIZE
>     flash : ORIGIN = 0x08020000, LENGTH = 0x00100000 - 0x20000
>     ccm   : ORIGIN = 0x10000000, LENGTH = 0x00010000
>}
>
>hal_vsr_table = 0x20000000;
>hal_virtual_vector_table = hal_vsr_table + 98*4;
>#if defined(CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT)
>hal_virtual_vector_table_end = hal_virtual_vector_table + 64*4;
>#else // zero size virtual vector table
>hal_virtual_vector_table_end = hal_virtual_vector_table;
>#endif
>
>// SRAM is 128k.
>hal_startup_stack = 0x20000000 + 1024*128;
>
>SECTIONS
>{
>     SECTIONS_BEGIN
>     USER_SECTION (ccm, ccm, 0x10000000 (NOLOAD), LMA_EQ_VMA)
>     SECTION_rom_vectors (flash, 0x08020000, LMA_EQ_VMA)
>     SECTION_RELOCS (flash, ALIGN (0x8), LMA_EQ_VMA)
>     SECTION_text (flash, ALIGN (0x8), LMA_EQ_VMA)
>     SECTION_fini (flash, ALIGN (0x8), LMA_EQ_VMA)
>     SECTION_rodata (flash, ALIGN (0x8), LMA_EQ_VMA)
>     SECTION_rodata1 (flash, ALIGN (0x8), LMA_EQ_VMA)
>     SECTION_fixup (flash, ALIGN (0x8), LMA_EQ_VMA)
>     SECTION_gcc_except_table (flash, ALIGN (0x8), LMA_EQ_VMA)
>     SECTION_eh_frame (flash, ALIGN (0x8), LMA_EQ_VMA)
>     SECTION_got (flash, ALIGN (0x8), LMA_EQ_VMA)
>     SECTION_sram (ram, hal_virtual_vector_table_end, FOLLOWING (.got))
>     SECTION_data (ram, ALIGN( 0x8), FOLLOWING (.sram))
>     SECTION_bss (ram, ALIGN (0x8), LMA_EQ_VMA)
>     CYG_LABEL_DEFN(__heap1) = ALIGN (0x8);
>     SECTIONS_END
>}
>
>*.h:
>#define CYGMEM_REGION_ram (0x20000000)
>#define CYGMEM_REGION_ram_SIZE 
>(0x00020000-CYGNUM_HAL_COMMON_INTERRUPTS_STACK_SIZE)
>#define CYGMEM_REGION_ram_ATTR (CYGMEM_REGION_ATTR_R |
>CYGMEM_REGION_ATTR_W)
>#define CYGMEM_REGION_ccm (0x10000000)
>#define CYGMEM_REGION_ccm_SIZE (0x00010000)
>#define CYGMEM_REGION_ccm_ATTR (CYGMEM_REGION_ATTR_R |
>CYGMEM_REGION_ATTR_W)
>#define CYGMEM_REGION_flash (0x08020000)
>#define CYGMEM_REGION_flash_SIZE (0x00100000 - 0x20000)
>#define CYGMEM_REGION_flash_ATTR (CYGMEM_REGION_ATTR_R | 
>CYGMEM_REGION_ATTR_W)
>#ifndef __ASSEMBLER__
>extern char CYG_LABEL_NAME (__heap1) [];
>#endif
>#define CYGMEM_SECTION_heap1 (CYG_LABEL_NAME (__heap1))
>#define CYGMEM_SECTION_heap1_SIZE 
>(CYGMEM_REGION_ram+CYGMEM_REGION_ram_SIZE - (size_t) CYG_LABEL_NAME 
>(__heap1))
>
>3. I am expecting output to be:
>IN JUMP
>IN APP
>
>But I do not get to IN APP.
>
>What am I doing wrong?
>
>I tried to jump to 0x08020004 address as it is where hal_reset_vsr is, 
>but still no luck.
>
>ROM startup build copies .data and .bss sections into ram, probably 
>these sections data gets overwritten.
>
>Do I need to shift addresses of SECTION_sram, SECTION_data, SECTION_bss
> 
>in app's memory layout?
>
>Oleg
>
>P.S:
>$ arm-none-eabi-readelf -h app.elf
>ELF Header:
>   Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
>   Class:                             ELF32
>   Data:                              2's complement, little endian
>   Version:                           1 (current)
>   OS/ABI:                            UNIX - System V
>   ABI Version:                       0
>   Type:                              EXEC (Executable file)
>   Machine:                           ARM
>   Version:                           0x1
>   Entry point address:               0x8020111
>   Start of program headers:          52 (bytes into file)
>   Start of section headers:          24148 (bytes into file)
>   Flags:                             0x5000002, has entry point, 
>Version5 EABI
>   Size of this header:               52 (bytes)
>   Size of program headers:           32 (bytes)
>   Number of program headers:         3
>   Size of section headers:           40 (bytes)
>   Number of section headers:         12
>   Section header string table index: 11
>
>$ arm-none-eabi-objdump -h app.elf
>
>app.elf:     file format elf32-littlearm
>
>Sections:
>Idx Name          Size      VMA       LMA       File off  Algn
>   0 .rom_vectors  00000008  08020000  08020000  00000098  2**0
>                   CONTENTS, ALLOC, LOAD, READONLY, CODE
>   1 .ARM.extab    0000003c  08020008  08020008  000000a0  2**2
>                   CONTENTS, ALLOC, LOAD, READONLY, DATA
>   2 .ARM.exidx    000000c8  08020048  08020048  000000e0  2**2
>                   CONTENTS, ALLOC, LOAD, READONLY, DATA
>   3 .text         0000586c  08020110  08020110  000001a8  2**3
>                   CONTENTS, ALLOC, LOAD, READONLY, CODE
>   4 .rodata       0000010d  08025980  08025980  00005a18  2**2
>                   CONTENTS, ALLOC, LOAD, READONLY, DATA
>   5 .eh_frame     00000008  08025a90  08025a90  00005b25  2**0
>                   ALLOC
>   6 .data         00000268  20000288  08025a98  00005b28  2**3
>                   CONTENTS, ALLOC, LOAD, DATA
>   7 .bss          000034e8  200004f0  08025d00  00005d90  2**3
>                   ALLOC
>   8 .ARM.attributes 0000002d  00000000  00000000  00005d90  2**0
>                   CONTENTS, READONLY
>   9 .comment      0000002a  00000000  00000000  00005dbd  2**0
>                   CONTENTS, READONLY

Oleg

I run a similar configuration on a custom board.
Starting an application located in flash from redboot.

You should read the application start address from the reset vector.
The entry point address is variable because of your linker config.
The only fix reference is the reset vector address.

You have to set the the stack pointer and jump to the address stored at the reset vector entry.

#define HAL_PLF_ARCH_GETRESETVECTOR(__reset,__vector)      \
{                                                       \
    __reset = *((unsigned long*)(__vector+4));          \
    register volatile CYG_ADDRESS __stack_ptr asm("sp");\
    __stack_ptr  = (*((unsigned long*)(__vector)));     \
}

// 'exec' must not a stack variable, 
// because stackpointer could be changed by platform macro
static volatile unsigned long exec; 
HAL_PLF_ARCH_GETRESETVECTOR(exec, 0x08002000);  // use or load address here
((void (*)(void))exec)();

Rainer



-- 
Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos
and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss



More information about the Ecos-discuss mailing list