title: Cortex-M0+ Linker Script and Startup Code
body: <p>I am trying to learn the startup process of an ARM processor by writing my own startup code and linker script. The chip I use is an LPC810, and I followed the examples from <a href="http://midibel.com/blink0.html" rel="noreferrer">http://midibel.com/blink0.html</a>, and both examples workes on my board, so the circuit is OK. Then, I try to implement a complete list of Exception and IRQ handler, but then the code does not start. I only have a st-link broken off from a NUCLEO board but I don't know how to debug it. Plus, the LPC chip is just plugged on a breadboard so I would try to avoid connecting more wires since many holes are already used or blocked by the ISP programming wires.</p>
  
  <p>This is the linker script <code>lpc810.ld</code>:</p>
  
  <pre><code>ENTRY(Reset_Handler);
  MEMORY {
      FLASH(rx) : ORIGIN = 0x0, LENGTH = 0x1000 /* 4K */
      RAM(rwx) : ORIGIN = 0x10000000, LENGTH = 0x400 /* 1K */
  }
  
  SECTIONS {
      . = ORIGIN(FLASH);
      .text : {
          KEEP(* (.isr_vectors));
          . = ALIGN(4);
          __vec_end__ = .;
          /*. = 0xC4;*/ /* End of vectors */
          * (.text);
          . = ALIGN(4);
          __end_text__ = .;
      } &gt; FLASH
  
      __flash_sdata__ = .;
  
      .data : AT(__flash_sdata__){
          __data_start__ = .;
          * (.data);
          . = ALIGN(4);
      __data_end__ = .;
      } &gt; RAM
  
      .bss : {
          __bss_start__ = .;
           * (.bss);
          . = ALIGN(4);
          _bss_end__ = .;
      }
      __stack_top = ORIGIN(RAM) + LENGTH(RAM);
  }
  
  _end = .;
  PROVIDE(end = .);
  </code></pre>
  
  <p>This is the startup code <code>crt0.S</code>:</p>
  
  <pre><code>/*
  This is the startup file for LPC81x. The C definition of the vector tables are defined in vector.c
  */
  .section .isr_vectors
  
  .align 2
  
  .long __stack_top
  .long Reset_Handler
  .long NMI_Handler
  .long HardFault_Handler
  .long 0
  .long 0
  .long 0
  .long 0
  .long 0
  .long 0
  .long 0
  .long SVCall_Handler
  .long 0
  .long 0
  .long PendSV_Handler
  .long SysTick_Handler
  .long 0
  
  /* IRQ 0 */
  .long SPI0_IRQ
  .long SPI1_IRQ
  .long 0
  .long UART0_IRQ
  .long UART1_IRQ
  .long UART2_IRQ
  .long 0
  .long 0
  /* IRQ 8 */
  .long I2C0_IRQ
  .long SCT_IRQ
  .long MRT_IRQ
  .long CMP_IRQ
  .long WDT_IRQ
  .long BOD_IRQ
  .long 0
  .long WKT_IRQ
  /* IRQ 16 */
  .long 0
  .long 0
  .long 0
  .long 0
  .long 0
  .long 0
  .long 0
  .long 0
  /* IRQ 24 */
  .long PININT0_IRQ
  .long PININT1_IRQ
  .long PININT2_IRQ
  .long PININT3_IRQ
  .long PININT4_IRQ
  .long PININT5_IRQ
  .long PININT6_IRQ
  .long PININT7_IRQ
  
  .text
  .align
  
  .global Reset_Handler
  Reset_Handler:
      b main
  </code></pre>
  
  <p>I know I am supposed to initialize <code>.data</code> <code>.bss</code> and other stuff, but since the minimal example doesn't initialize them, the problem might not lie there. The <code>vector.c</code> which contains the symbols:</p>
  
  <pre><code>extern void Reset_Handler(void);
  extern void NMI_Handler(void);
  extern void HardFault_Handler(void);
  extern void SVCall_Handler(void);
  extern void PendSV_Handler(void);
  extern void SysTick_Handler(void);
  
  extern void SPI0_IRQ(void);
  extern void SPI1_IRQ(void);
  extern void UART0_IRQ(void);
  extern void UART1_IRQ(void);
  extern void UART2_IRQ(void);
  extern void I2C0_IRQ(void);
  extern void SCT_IRQ(void);
  extern void MRT_IRQ(void);
  extern void CMP_IRQ(void);
  extern void WDT_IRQ(void);
  extern void BOD_IRQ(void);
  extern void WKT_IRQ(void);
  extern void PININT0_IRQ(void);
  extern void PININT1_IRQ(void);
  extern void PININT2_IRQ(void);
  extern void PININT3_IRQ(void);
  extern void PININT4_IRQ(void);
  extern void PININT5_IRQ(void);
  extern void PININT6_IRQ(void);
  extern void PININT7_IRQ(void);
  
  __attribute__((naked)) 
  void _unhandled_exception(void) {
      for(;;);
  }
  
  void NMI_Handler(void) __attribute__((weak, alias("_unhandled_exception")));
  void HardFault_Handler(void) __attribute__((weak, alias("_unhandled_exception")));
  void SVCall_Handler(void) __attribute__((weak, alias("_unhandled_exception")));
  void PendSV_Handler(void) __attribute__((weak, alias("_unhandled_exception")));
  void SysTick_Handler(void) __attribute__((weak, alias("_unhandled_exception")));
  
  void SPI0_IRQ(void) __attribute__((weak, alias("_unhandled_exception")));
  void SPI1_IRQ(void) __attribute__((weak, alias("_unhandled_exception")));
  void UART0_IRQ(void) __attribute__((weak, alias("_unhandled_exception")));
  void UART1_IRQ(void) __attribute__((weak, alias("_unhandled_exception")));
  void UART2_IRQ(void) __attribute__((weak, alias("_unhandled_exception")));
  void I2C0_IRQ(void) __attribute__((weak, alias("_unhandled_exception")));
  void SCT_IRQ(void) __attribute__((weak, alias("_unhandled_exception")));
  void MRT_IRQ(void) __attribute__((weak, alias("_unhandled_exception")));
  void CMP_IRQ(void) __attribute__((weak, alias("_unhandled_exception")));
  void WDT_IRQ(void) __attribute__((weak, alias("_unhandled_exception")));
  void BOD_IRQ(void) __attribute__((weak, alias("_unhandled_exception")));
  void WKT_IRQ(void) __attribute__((weak, alias("_unhandled_exception")));
  void PININT0_IRQ(void) __attribute__((weak, alias("_unhandled_exception")));
  void PININT1_IRQ(void) __attribute__((weak, alias("_unhandled_exception")));
  void PININT2_IRQ(void) __attribute__((weak, alias("_unhandled_exception")));
  void PININT3_IRQ(void) __attribute__((weak, alias("_unhandled_exception")));
  void PININT4_IRQ(void) __attribute__((weak, alias("_unhandled_exception")));
  void PININT5_IRQ(void) __attribute__((weak, alias("_unhandled_exception")));
  void PININT6_IRQ(void) __attribute__((weak, alias("_unhandled_exception")));
  void PININT7_IRQ(void) __attribute__((weak, alias("_unhandled_exception")));
  </code></pre>
  
  <p>The <code>main.c</code> which is basically unmodified from the tutorial:</p>
  
  <pre><code>/*
  BLINK0:
    A minimal "Blinky" for NXP-LPC810 miniboard
    A single-file example using only out-of-the-box arm-gcc compiler and no crt0
    Using default reset state values for everything
    Pressing the ISP button will change blink rate
    WARN: due to missing crt0 - no init of data/bss (see blink1 ;) )
  */
  
  typedef unsigned int volatile * vp;
  
  void main()
  {
    *(vp)0x4000c1c0 = 0xffffffbfUL;       // PINENABLE0 (disable SWclk/dio)
    *(vp)0xa0002000 |= (1 &lt;&lt; 2);          // DIR0 (set pinio-2 to output)
    for (;;)
    {
      *(vp)0xa0002100 ^= (1 &lt;&lt; 2);        // PIN0 - toggle LED
  
      // Some busy loop waiting...
      volatile long vaste = *(vp)0xa0002100 &amp; (1 &lt;&lt; 1) ? 250000 : 50000;  // PIN0 (fast blink when ISP pressed)
      while (vaste &gt; 0) --vaste;
    }
  }
  </code></pre>
  
  <p>The <code>CFLAGS</code> I am using:</p>
  
  <pre><code>CFLAGS=-Os -mthumb -mcpu=cortex-m0plus -nostartfiles -Wl,-T$(LDS),-nostdlib,-Map=$(TGT).map
  </code></pre>
  
  <p><em>Update</em></p>
  
  <p>This is the disassembly code generated by <code>arm-none-eabi-objdump -d</code>:</p>
  
  <p>main.elf:     file format elf32-littlearm</p>
  
  <pre><code>Disassembly of section .text:
  
  00000000 &lt;_unhandled_exception-0xc4&gt;:
     0:   10000400    .word   0x10000400
     4:   000000c8    .word   0x000000c8
     8:   000000c5    .word   0x000000c5
     c:   000000c5    .word   0x000000c5
      ...
    2c:   000000c5    .word   0x000000c5
      ...
    38:   000000c5    .word   0x000000c5
    3c:   000000c5    .word   0x000000c5
    40:   00000000    .word   0x00000000
    44:   000000c5    .word   0x000000c5
    48:   000000c5    .word   0x000000c5
    4c:   00000000    .word   0x00000000
    50:   000000c5    .word   0x000000c5
    54:   000000c5    .word   0x000000c5
    58:   000000c5    .word   0x000000c5
      ...
    64:   000000c5    .word   0x000000c5
    68:   000000c5    .word   0x000000c5
    6c:   000000c5    .word   0x000000c5
    70:   000000c5    .word   0x000000c5
    74:   000000c5    .word   0x000000c5
    78:   000000c5    .word   0x000000c5
    7c:   00000000    .word   0x00000000
    80:   000000c5    .word   0x000000c5
      ...
    a4:   000000c5    .word   0x000000c5
    a8:   000000c5    .word   0x000000c5
    ac:   000000c5    .word   0x000000c5
    b0:   000000c5    .word   0x000000c5
    b4:   000000c5    .word   0x000000c5
    b8:   000000c5    .word   0x000000c5
    bc:   000000c5    .word   0x000000c5
    c0:   000000c5    .word   0x000000c5
  
  000000c4 &lt;_unhandled_exception&gt;:
    c4:   e7fe        b.n c4 &lt;_unhandled_exception&gt;
      ...
  
  000000c8 &lt;Reset_Handler&gt;:
    c8:   e000        b.n cc &lt;__end_text__&gt;
    ca:   46c0        nop         ; (mov r8, r8)
  
  Disassembly of section .text.startup:
  
  000000cc &lt;main&gt;:
    cc:   4b0d        ldr r3, [pc, #52]   ; (104 &lt;__end_text__+0x38&gt;)
    ce:   2241        movs    r2, #65 ; 0x41
    d0:   4252        negs    r2, r2
    d2:   601a        str r2, [r3, #0]
    d4:   4b0c        ldr r3, [pc, #48]   ; (108 &lt;__end_text__+0x3c&gt;)
    d6:   2104        movs    r1, #4
    d8:   681a        ldr r2, [r3, #0]
    da:   b082        sub sp, #8
    dc:   430a        orrs    r2, r1
    de:   601a        str r2, [r3, #0]
    e0:   4b0a        ldr r3, [pc, #40]   ; (10c &lt;__end_text__+0x40&gt;)
    e2:   2104        movs    r1, #4
    e4:   681a        ldr r2, [r3, #0]
    e6:   404a        eors    r2, r1
    e8:   601a        str r2, [r3, #0]
    ea:   681b        ldr r3, [r3, #0]
    ec:   079a        lsls    r2, r3, #30
    ee:   d501        bpl.n   f4 &lt;main+0x28&gt;
    f0:   4b07        ldr r3, [pc, #28]   ; (110 &lt;__end_text__+0x44&gt;)
    f2:   e000        b.n f6 &lt;main+0x2a&gt;
    f4:   4b07        ldr r3, [pc, #28]   ; (114 &lt;__end_text__+0x48&gt;)
    f6:   9301        str r3, [sp, #4]
    f8:   9b01        ldr r3, [sp, #4]
    fa:   2b00        cmp r3, #0
    fc:   ddf0        ble.n   e0 &lt;main+0x14&gt;
    fe:   9b01        ldr r3, [sp, #4]
   100:   3b01        subs    r3, #1
   102:   e7f8        b.n f6 &lt;main+0x2a&gt;
   104:   4000c1c0    .word   0x4000c1c0
   108:   a0002000    .word   0xa0002000
   10c:   a0002100    .word   0xa0002100
   110:   0003d090    .word   0x0003d090
   114:   0000c350    .word   0x0000c350
  </code></pre>
  
  <p>The symbol table generated by <code>arm-none-eabi-nm -n</code>:</p>
  
  <pre><code>000000c4 W BOD_IRQ
  000000c4 W CMP_IRQ
  000000c4 W HardFault_Handler
  000000c4 W I2C0_IRQ
  000000c4 W MRT_IRQ
  000000c4 W NMI_Handler
  000000c4 W PendSV_Handler
  000000c4 W PININT0_IRQ
  000000c4 W PININT1_IRQ
  000000c4 W PININT2_IRQ
  000000c4 W PININT3_IRQ
  000000c4 W PININT4_IRQ
  000000c4 W PININT5_IRQ
  000000c4 W PININT6_IRQ
  000000c4 W PININT7_IRQ
  000000c4 W SCT_IRQ
  000000c4 W SPI0_IRQ
  000000c4 W SPI1_IRQ
  000000c4 W SVCall_Handler
  000000c4 W SysTick_Handler
  000000c4 W UART0_IRQ
  000000c4 W UART1_IRQ
  000000c4 W UART2_IRQ
  000000c4 T _unhandled_exception
  000000c4 T __vec_end__
  000000c4 W WDT_IRQ
  000000c4 W WKT_IRQ
  000000c8 T Reset_Handler
  000000cc T __end_text__
  000000cc T __flash_sdata__
  000000cc T main
  10000000 T _bss_end__
  10000000 T __bss_start__
  10000000 T __data_end__
  10000000 T __data_start__
  10000000 T _end
  10000400 A __stack_top
  </code></pre>
  
  <p>The <code>main.map</code>:</p>
  
  <pre><code>Memory Configuration
  
  Name             Origin             Length             Attributes
  FLASH            0x0000000000000000 0x0000000000001000 xr
  RAM              0x0000000010000000 0x0000000000000400 xrw
  *default*        0x0000000000000000 0xffffffffffffffff
  
  Linker script and memory map
  
                  0x0000000000000000                . = ORIGIN (FLASH)
  
  .text           0x0000000000000000       0xcc
   *(.isr_vectors)
   .isr_vectors   0x0000000000000000       0xc4 crt0.o
                  0x00000000000000c4                . = ALIGN (0x4)
                  0x00000000000000c4                __vec_end__ = .
   *(.text)
   .text          0x00000000000000c4        0x0 main.o
   .text          0x00000000000000c4        0x2 vectors.o
                  0x00000000000000c4                SVCall_Handler
                  0x00000000000000c4                PININT5_IRQ
                  0x00000000000000c4                HardFault_Handler
                  0x00000000000000c4                SysTick_Handler
                  0x00000000000000c4                SPI1_IRQ
                  0x00000000000000c4                PendSV_Handler
                  0x00000000000000c4                NMI_Handler
                  0x00000000000000c4                CMP_IRQ
                  0x00000000000000c4                SPI0_IRQ
                  0x00000000000000c4                WKT_IRQ
                  0x00000000000000c4                PININT0_IRQ
                  0x00000000000000c4                PININT2_IRQ
                  0x00000000000000c4                PININT6_IRQ
                  0x00000000000000c4                PININT1_IRQ
                  0x00000000000000c4                MRT_IRQ
                  0x00000000000000c4                WDT_IRQ
                  0x00000000000000c4                UART2_IRQ
                  0x00000000000000c4                PININT7_IRQ
                  0x00000000000000c4                SCT_IRQ
                  0x00000000000000c4                I2C0_IRQ
                  0x00000000000000c4                PININT4_IRQ
                  0x00000000000000c4                BOD_IRQ
                  0x00000000000000c4                UART0_IRQ
                  0x00000000000000c4                _unhandled_exception
                  0x00000000000000c4                PININT3_IRQ
                  0x00000000000000c4                UART1_IRQ
   *fill*         0x00000000000000c6        0x2 
   .text          0x00000000000000c8        0x4 crt0.o
                  0x00000000000000c8                Reset_Handler
                  0x00000000000000cc                . = ALIGN (0x4)
                  0x00000000000000cc                __end_text__ = .
                  0x00000000000000cc                __flash_sdata__ = .
  
  .glue_7         0x00000000000000cc        0x0
   .glue_7        0x0000000000000000        0x0 linker stubs
  
  .glue_7t        0x00000000000000cc        0x0
   .glue_7t       0x0000000000000000        0x0 linker stubs
  
  .vfp11_veneer   0x00000000000000cc        0x0
   .vfp11_veneer  0x0000000000000000        0x0 linker stubs
  
  .v4_bx          0x00000000000000cc        0x0
   .v4_bx         0x0000000000000000        0x0 linker stubs
  
  .text.startup   0x00000000000000cc       0x4c
   .text.startup  0x00000000000000cc       0x4c main.o
                  0x00000000000000cc                main
  
  .iplt           0x0000000000000118        0x0
   .iplt          0x0000000000000000        0x0 crt0.o
  
  .rel.dyn        0x0000000000000118        0x0
   .rel.iplt      0x0000000000000000        0x0 crt0.o
  
  .data           0x0000000010000000        0x0 load address 0x00000000000000cc
                  0x0000000010000000                __data_start__ = .
   *(.data)
   .data          0x0000000010000000        0x0 main.o
   .data          0x0000000010000000        0x0 vectors.o
   .data          0x0000000010000000        0x0 crt0.o
                  0x0000000010000000                . = ALIGN (0x4)
                  0x0000000010000000                __data_end__ = .
  
  .igot.plt       0x0000000010000000        0x0 load address 0x00000000000000cc
   .igot.plt      0x0000000000000000        0x0 crt0.o
  
  .bss            0x0000000010000000        0x0 load address 0x00000000000000cc
                  0x0000000010000000                __bss_start__ = .
   *(.bss)
   .bss           0x0000000010000000        0x0 main.o
   .bss           0x0000000010000000        0x0 vectors.o
   .bss           0x0000000010000000        0x0 crt0.o
                  0x0000000010000000                . = ALIGN (0x4)
                  0x0000000010000000                _bss_end__ = .
                  0x0000000010000400                __stack_top = (ORIGIN (RAM) + 0x400)
                  0x0000000010000000                _end = .
                  0x0000000010000000                PROVIDE (end, .)
  LOAD main.o
  LOAD vectors.o
  LOAD crt0.o
  START GROUP
  LOAD /usr/lib/gcc/arm-none-eabi/4.8.2/armv6-m/libgcc.a
  LOAD /usr/lib/gcc/arm-none-eabi/4.8.2/../../../arm-none-eabi/lib/armv6-m/libc.a
  END GROUP
  OUTPUT(main.elf elf32-littlearm)
  
  .comment        0x0000000000000000       0x1f
   .comment       0x0000000000000000       0x1f main.o
                                           0x20 (size before relaxing)
   .comment       0x0000000000000000       0x20 vectors.o
  
  .ARM.attributes
                  0x0000000000000000       0x30
   .ARM.attributes
                  0x0000000000000000       0x32 main.o
   .ARM.attributes
                  0x0000000000000032       0x32 vectors.o
   .ARM.attributes
                  0x0000000000000064       0x22 crt0.o
  </code></pre>