Stack Pointer does not load at the startup in ARM Cortex M4 (Tiva C Series TM4C123GH6PM)

2

I'm trying to write the most simple program for Tiva C launchpad. Stack pointer value and program counter value are automaticaly taken from the two first 32-bits words of flash. But, for somehow reason, when I debug with gdb, the stack pointer gets 0x0. This causes that program fails. I'm using this instructions to debug:

(gdb) target extended-remote :3333
(gdb) monitor reset halt
(gdb) load
(gdb) monitor reset init

Program in assembly is startup.s:

        .syntax unified

        .section .vector_interrupt, "x"

    g_pfnVectors:
        .word 0x20007FFF
        .word _Reset

        .text
    .global _Reset
    _Reset:
        mov   r0, #0
        b stop

    stop:   
        add   r0, r0, #1
        b stop 

the linker file Tiva.lds:

ENTRY(_Reset)

MEMORY
{
    FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x00040000
    SRAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000
}

SECTIONS {
        .vector_interrupt : {
        KEEP(*(.vector_interrupt));
    } > FLASH

    .text : {
        . = 0x0000026c;
        * (.text);
    } > FLASH

}

and the makefile:

gcc=arm-none-eabi-gcc
objcopy=arm-none-eabi-objcopy

FLAGS= -ggdb3 -nostdlib -std=c99 -mcpu=cortex-m4 \
       -mfloat-abi=softfp -mfpu=fpv4-sp-d16 -Wall \
       -Werror -nostartfiles

csum.bin: csum.elf
    $(objcopy) -O binary csum.elf csum.bin

csum.elf: startup.s
    $(gcc) $(FLAGS) -T Tiva.lds -o csum.elf \
    startup.s

openocd:
    openocd -f ../openOCD/ek-tm4c123gxl.cfg

What is wrong?

Actualization

I was trying to avoid put the exception handlers. However, Now I put them. The problem is that i'm getting an UsageFault at startup.

I did this modifications: startup.s:

.syntax unified

        .section .vector_interrupt, "x"
g_pfnVectors:
        .word   _stack_start
        .word   _Reset
        .word   NMI           /* NMI Handler */
        .word   HardFault     /* Hard Fault Handler */
        .word   MemManage     /* MPU Fault Handler */
        .word   BusFault      /* Bus Fault Handler */
        .word   UsageFault    /* Usage Fault Handler */
        .word   0             /* Reserved */
        .word   0             /* Reserved */
        .word   0             /* Reserved */
        .word   0             /* Reserved */
        .word   SVC           /* SVCall Handler */
        .word   DebugMon      /* Debug Monitor Handler */
        .word   0             /* Reserved */
        .word   PendSV        /* PendSV Handler */
        .word   SysTick       /* SysTick Handler */

        .text
.global _Reset
_Reset:
        mov   r0, #0
        b stop

stop:   
        add   r0, r0, #1
        b stop               @ Infinite loop to stop execution



        .align  1
        .thumb_func
        .weak   Default_Handler
        .type   Default_Handler, %function
Default_Handler:
        b   .

/* Macro to define default handlers */
        .macro  def_handler handler_name
            .weak   \handler_name
            .set    \handler_name, Default_Handler
        .endm

        def_handler NMI
        def_handler HardFault
        def_handler MemManage
        def_handler BusFault
        def_handler UsageFault
        def_handler SVC
        def_handler DebugMon
        def_handler PendSV
        def_handler SysTick
        def_handler DEF_IRQHandler

Tiva.lds:

ENTRY(_Reset)

MEMORY
{
    FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x00040000
    SRAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000
}

_stack_start = ORIGIN(SRAM)+LENGTH(SRAM);

SECTIONS {
        .text : {
            KEEP(*(.vector_interrupt));
            * (.text);
        } > FLASH

}

This is the output from arm-none-eabi-objdump -d csum.elf

csum.elf:     file format elf32-littlearm


Disassembly of section .text:

00000000 <g_pfnVectors>:
   0:   20008000    .word   0x20008000
   4:   00000040    .word   0x00000040
   8:   0000004d    .word   0x0000004d
   c:   0000004d    .word   0x0000004d
  10:   0000004d    .word   0x0000004d
  14:   0000004d    .word   0x0000004d
  18:   0000004d    .word   0x0000004d
    ...
  2c:   0000004d    .word   0x0000004d
  30:   0000004d    .word   0x0000004d
  34:   00000000    .word   0x00000000
  38:   0000004d    .word   0x0000004d
  3c:   0000004d    .word   0x0000004d

00000040 <_Reset>:
  40:   f04f 0000   mov.w   r0, #0
  44:   e7ff        b.n 46 <stop>

00000046 <stop>:
  46:   f100 0001   add.w   r0, r0, #1
  4a:   e7fc        b.n 46 <stop>

0000004c <BusFault>:
  4c:   f7ff bff8   b.w 4c <BusFault>

The reasons for the UsageFault can be:

  • An undefined instruction

– An illegal unaligned access

– Invalid state on instruction execution

– An error on exception return

but i don't figure out what is the reason.

gcc
arm
cortex-m
bare-metal
asked on Stack Overflow Nov 15, 2017 by DanielS • edited Nov 15, 2017 by DanielS

1 Answer

3

Writing in ARM assembly is tricky. There were three problems with this code.

  1. The .vector_interrupt section did not make it to the binary file because it did not have the ALLOC attribute. objcopy ignores sections without the ALLOC attribute. As a result, the initial stack pointer and reset vector were zeroes. To fix this, the section attributes should read "xa":

    .section .vector_interrupt, "xa"
    
  2. Another problem: initial stack pointer is unaligned. Change it to:

    .word 0x20008000
    

This is assuming the MCU has at least 32KB RAM.

  1. Branch target addresses should have the LSB bit set to one to indicate Thumb mode. Cortex-M4 supports the Thumb instruction set only, therefore, it generates a fault when trying to jump to an even address. In order to let the assembler generate correct address values, the .thumb_func should precede each label that identified a branch target.

See https://sourceware.org/binutils/docs/as/ARM-Directives.html

answered on Stack Overflow Nov 15, 2017 by A.K. • edited Nov 15, 2017 by A.K.

User contributions licensed under CC BY-SA 3.0