Mistake on this page?
Report an issue in GitHub or email us

Bootstrap

Bring in CMSIS-Core files

To work with Mbed OS, you need to implement CMSIS-Core support for your device as the CMSIS-Core documentation describes. CMSIS-Core files are usually in the mbed-os\targets\TARGET_<VENDOR>\TARGET_MCU_<FAMILY>\TARGET_<MCUNAME>\device directory.

Startup files

The startup file contains interrupt vectors and low-level core and platform initialization routines. You need to provide a version of this file for each Mbed OS supported toolchain.

For more information about startup files, please see the CMSIS documentation.

Linker scripts

After adding the core files, the next step is to add linker scripts for Mbed OS. To do this, you can either use the linker scripts below and change the defines for your target or you can modify an existing linker script to be compatible with Mbed OS. You need to provide a version of the linker script for each Mbed OS supported toolchain.

If you are updating your own linker script, you must:

  • Reserve space for the RAM vector table.
  • Define the start of the heap:
    • Arm - The heap starts immediately after the region RW_IRAM1.
    • GCC_ARM - The heap starts at the symbol __end__.
    • IAR - The heap is the HEAP region.
    • Add defines for a relocatable application - MBED_APP_START and MBED_APP_SIZE.
    • Add preprocessing directive #! armcc -E (ARM compiler only).

If you are using the below linker script, then you need to update all the defines in the /* Device specific values */ section for your target.

Arm linker script template:

#! armcc -E

/* Device specific values */

#define ROM_START   0x08000000
#define ROM_SIZE    0x200000
#define RAM_START   0x20000000
#define RAM_SIZE    0x30000
#define VECTORS     107   /* This value must match NVIC_NUM_VECTORS */

/* Common - Do not change */

#if !defined(MBED_APP_START)
  #define MBED_APP_START ROM_START
#endif

#if !defined(MBED_APP_SIZE)
  #define MBED_APP_SIZE ROM_SIZE
#endif

/* Round up VECTORS_SIZE to 8 bytes */
#define VECTORS_SIZE (((VECTORS * 4) + 7) & ~7)

LR_IROM1 MBED_APP_START MBED_APP_SIZE  {

  ER_IROM1 MBED_APP_START MBED_APP_SIZE  {
    *.o (RESET, +First)
    *(InRoot$$Sections)
    .ANY (+RO)
  }

  RW_IRAM1 (RAM_START + VECTORS_SIZE) (RAM_SIZE - VECTORS_SIZE)  {  ; RW data
    .ANY (+RW +ZI)
  }
}

IAR linker script template:

/* Device specific values */

define symbol ROM_START   = 0x08000000;
define symbol ROM_SIZE    = 0x200000;
define symbol RAM_START   = 0x20000000;
define symbol RAM_SIZE    = 0x30000;
define symbol VECTORS     = 107; /* This value must match NVIC_NUM_VECTORS */
define symbol HEAP_SIZE   = 0x10000;

/* Common - Do not change */

if (!isdefinedsymbol(MBED_APP_START)) {
    define symbol MBED_APP_START = ROM_START;
}

if (!isdefinedsymbol(MBED_APP_SIZE)) {
    define symbol MBED_APP_SIZE = ROM_SIZE;
}

/* Round up VECTORS_SIZE to 8 bytes */
define symbol VECTORS_SIZE = ((VECTORS * 4) + 7) & ~7;
define symbol RAM_REGION_START = RAM_START + VECTORS_SIZE;
define symbol RAM_REGION_SIZE = RAM_SIZE - VECTORS_SIZE;
define symbol ISR_STACK_SIZE = 0x400;

define memory mem with size = 4G;
define region ROM_region = mem:[from MBED_APP_START size MBED_APP_SIZE];
define region RAM_region = mem:[from RAM_REGION_START size RAM_REGION_SIZE];

define block CSTACK    with alignment = 8, size = ISR_STACK_SIZE   { };
define block HEAP      with alignment = 8, size = HEAP_SIZE     { };

initialize by copy { readwrite };
do not initialize  { section .noinit };

place at address mem: MBED_APP_START { readonly section .intvec };

place in ROM_region   { readonly };
place in RAM_region   { readwrite,
                        block CSTACK, block HEAP };

GCC linker script template:

/* Device specific values */

#define ROM_START   0x08000000
#define ROM_SIZE    0x200000
#define RAM_START   0x20000000
#define RAM_SIZE    0x30000
#define VECTORS     107   /* This value must match NVIC_NUM_VECTORS */

/* Common - Do not change */

#if !defined(MBED_APP_START)
  #define MBED_APP_START ROM_START
#endif

#if !defined(MBED_APP_SIZE)
  #define MBED_APP_SIZE ROM_SIZE
#endif

/* Round up VECTORS_SIZE to 8 bytes */
#define VECTORS_SIZE (((VECTORS * 4) + 7) & 0xFFFFFFF8)

MEMORY
{
    FLASH (rx)   : ORIGIN = MBED_APP_START, LENGTH = MBED_APP_SIZE
    RAM (rwx)    : ORIGIN = RAM_START + VECTORS_SIZE, LENGTH = RAM_SIZE - VECTORS_SIZE
}

/* Linker script to place sections and symbol values. Should be used together
 * with other linker script that defines memory regions FLASH and RAM.
 * It references following symbols, which must be defined in code:
 *   Reset_Handler : Entry of reset handler
 *
 * It defines following symbols, which code can use without definition:
 *   __exidx_start
 *   __exidx_end
 *   __etext
 *   __data_start__
 *   __preinit_array_start
 *   __preinit_array_end
 *   __init_array_start
 *   __init_array_end
 *   __fini_array_start
 *   __fini_array_end
 *   __data_end__
 *   __bss_start__
 *   __bss_end__
 *   __end__
 *   end
 *   __HeapLimit
 *   __StackLimit
 *   __StackTop
 *   __stack
 */
ENTRY(Reset_Handler)

SECTIONS
{
    .text :
    {
        KEEP(*(.isr_vector))
        *(.text*)

        KEEP(*(.init))
        KEEP(*(.fini))

        /* .ctors */
        *crtbegin.o(.ctors)
        *crtbegin?.o(.ctors)
        *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
        *(SORT(.ctors.*))
        *(.ctors)

        /* .dtors */
         *crtbegin.o(.dtors)
         *crtbegin?.o(.dtors)
         *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
         *(SORT(.dtors.*))
         *(.dtors)

        *(.rodata*)

        KEEP(*(.eh_frame*))
    } > FLASH

    .ARM.extab :
    {
        *(.ARM.extab* .gnu.linkonce.armextab.*)
    } > FLASH

    __exidx_start = .;
    .ARM.exidx :
    {
        *(.ARM.exidx* .gnu.linkonce.armexidx.*)
    } > FLASH
    __exidx_end = .;

    /* Location counter can end up 2byte aligned with narrow Thumb code but
       __etext is assumed by startup code to be the LMA of a section in RAM
       which must be 4byte aligned */
    __etext = ALIGN (4);

    .data : AT (__etext)
    {
        __data_start__ = .;
        *(vtable)
        *(.data*)

        . = ALIGN(4);
        /* preinit data */
        PROVIDE_HIDDEN (__preinit_array_start = .);
        KEEP(*(.preinit_array))
        PROVIDE_HIDDEN (__preinit_array_end = .);

        . = ALIGN(4);
        /* init data */
        PROVIDE_HIDDEN (__init_array_start = .);
        KEEP(*(SORT(.init_array.*)))
        KEEP(*(.init_array))
        PROVIDE_HIDDEN (__init_array_end = .);


        . = ALIGN(4);
        /* finit data */
        PROVIDE_HIDDEN (__fini_array_start = .);
        KEEP(*(SORT(.fini_array.*)))
        KEEP(*(.fini_array))
        PROVIDE_HIDDEN (__fini_array_end = .);

        KEEP(*(.jcr*))
        . = ALIGN(4);
        /* All data end */
        __data_end__ = .;

    } > RAM

    .bss :
    {
        . = ALIGN(4);
        __bss_start__ = .;
        *(.bss*)
        *(COMMON)
        . = ALIGN(4);
        __bss_end__ = .;
    } > RAM

    .heap (COPY):
    {
        __end__ = .;
        PROVIDE(end = .);
        *(.heap*)
        __HeapLimit = .;
    } > RAM

    /* .stack_dummy section doesn't contains any symbols. It is only
     * used for linker to calculate size of stack sections, and assign
     * values to stack symbols later */
    .stack_dummy (COPY):
    {
        *(.stack*)
    } > RAM

    /* Set stack top to end of RAM, and stack limit move down by
     * size of stack_dummy section */
    __StackTop = ORIGIN(RAM) + LENGTH(RAM);
    __StackLimit = __StackTop - SIZEOF(.stack_dummy);
    PROVIDE(__stack = __StackTop);

    /* Check if data + heap + stack exceeds RAM limit */
    ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
}

Other required files

  • Make sure your CMSIS-Core implementation contains the device.h header.
  • Extend CMSIS-Core by adding the file mbed-os\targets\TARGET_VENDOR\TARGET_MCUNAME\cmsis.h. This header file includes device-specific headers that include CMSIS-Core. It must also include cmsic_nvic.h.
  • Add the mbed-os\targets\TARGET_VENDOR\TARGET_MCUNAME\cmsis_nvic.h header file. This contains the define NVIC_NUM_VECTORS, which is the number of vectors the devices has, and NVIC_RAM_VECTOR_ADDRESS, which is the address of the RAM vector table. Mbed OS relocates the vectors from the initial location in ROM to the provided address in RAM and updates the VTOR register. NOTE: For devices without the VTOR register, you need to make sure the vectors are in the read-write memory before execution reaches the main function. In this case, you may also need to provide visualization of NVIC access functions. For details, please see the CMSIS NVIC documentation.
  • Define the initial stack pointer, INITIAL_SP, in mbed_rtx.h. This file is typically in mbed-os\targets\TARGET_VENDOR\mbed_rtx.h.
Important Information for this Arm website

This site uses cookies to store information on your computer. By continuing to use our site, you consent to our cookies. If you are not happy with the use of these cookies, please review our Cookie Policy to learn how they can be disabled. By disabling cookies, some features of the site will not work.