Makefile
ARMGNU = arm-none-eabi
AOPS = --warn --fatal-warnings -mcpu=cortex-m4
COPS = -Wall -Werror -O2 -nostdlib -nostartfiles -ffreestanding -mcpu=cortex-m4
all : so.bin
clean:
rm -f *.bin
rm -f *.o
rm -f *.elf
rm -f *.list
flash.o : flash.s
$(ARMGNU)-as $(AOPS) flash.s -o flash.o
so.o : so.c
$(ARMGNU)-gcc $(COPS) -mthumb -c so.c -o so.o
so.bin : flash.ld flash.o so.o
$(ARMGNU)-ld -o so.elf -T flash.ld flash.o so.o
$(ARMGNU)-objdump -D so.elf > so.list
$(ARMGNU)-objcopy so.elf so.bin -O binary
flash.ld
MEMORY
{
rom : ORIGIN = 0x00000000, LENGTH = 0x1000
ram : ORIGIN = 0x20000000, LENGTH = 0x1000
}
SECTIONS
{
.text : { *(.text*) } > rom
.rodata : { *(.rodata*) } > rom
.bss : { *(.bss*) } > ram
}
flash.s
.thumb
.thumb_func
.global _start
_start:
stacktop: .word 0x20001000
.word reset
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.thumb_func
reset:
bl notmain
b hang
.thumb_func
hang: b .
.thumb_func
.globl PUT32
PUT32:
str r1,[r0]
bx lr
so.c
extern void PUT32 ( unsigned int, unsigned int );
int notmain ( void )
{
PUT32(0x20000400,0x12345678);
return(0);
}
make
arm-none-eabi-as --warn --fatal-warnings -mcpu=cortex-m4 flash.s -o flash.o
arm-none-eabi-gcc -Wall -Werror -O2 -nostdlib -nostartfiles -ffreestanding -mcpu=cortex-m4 -mthumb -c so.c -o so.o
arm-none-eabi-ld -o so.elf -T flash.ld flash.o so.o
arm-none-eabi-objdump -D so.elf > so.list
arm-none-eabi-objcopy so.elf so.bin -O binary
examine disassembly to see that the vector table is in the right place and built right, could toss a global variable in and save a value to it (runtime) to see that that is in the correct place as well if you want.
Disassembly of section .text:
00000000 <_start>:
0: 20001000 andcs r1, r0, r0
4: 00000041 andeq r0, r0, r1, asr #32
8: 00000047 andeq r0, r0, r7, asr #32
c: 00000047 andeq r0, r0, r7, asr #32
10: 00000047 andeq r0, r0, r7, asr #32
14: 00000047 andeq r0, r0, r7, asr #32
18: 00000047 andeq r0, r0, r7, asr #32
1c: 00000047 andeq r0, r0, r7, asr #32
20: 00000047 andeq r0, r0, r7, asr #32
24: 00000047 andeq r0, r0, r7, asr #32
28: 00000047 andeq r0, r0, r7, asr #32
2c: 00000047 andeq r0, r0, r7, asr #32
30: 00000047 andeq r0, r0, r7, asr #32
34: 00000047 andeq r0, r0, r7, asr #32
38: 00000047 andeq r0, r0, r7, asr #32
3c: 00000047 andeq r0, r0, r7, asr #32
00000040 <reset>:
40: f000 f804 bl 4c <notmain>
44: e7ff b.n 46 <hang>
00000046 <hang>:
46: e7fe b.n 46 <hang>
00000048 <PUT32>:
48: 6001 str r1, [r0, #0]
4a: 4770 bx lr
0000004c <notmain>:
4c: b508 push {r3, lr}
4e: 4903 ldr r1, [pc, #12] ; (5c <notmain+0x10>)
50: 4803 ldr r0, [pc, #12] ; (60 <notmain+0x14>)
52: f7ff fff9 bl 48 <PUT32>
56: 2000 movs r0, #0
58: bd08 pop {r3, pc}
5a: bf00 nop
5c: 12345678 eorsne r5, r4, #120, 12 ; 0x7800000
60: 20000400 andcs r0, r0, r0, lsl #8
Looks good vector table in the right place, lsbit set on the vector table addresses, etc.
This is a very generic cortex-m program that should work on almost all cores some you may have to reduce the stack pointer init to 0x20000800 or smaller, likewise specify cortex-m0 on the command line instead of m4 to make it that much more generic, in this case it didnt generate any armv7-m thumb2 extensions.
See what your tool says about this so.elf file generated, it does get simpler than this (remove the bl notmain) and only link flash.s into an elf, but not much simpler than this. If it doesnt work then the problem may be something else, the tool may be looking for something. If this is really a tiva c part then maybe the lm4flash tool will work and you dont need any guis, otherwise openocd should work if you have a SWD solution (an st nucleo or discovery board, or you are running on a ti launchpad, or a jlink or an ftdi breakoutboard with the right ftdi part (one that supports mpsse and the voltages are the right level for your target). If it doesnt work then perhaps the tool is looking for something special in the elf file that is normally not required. I assume before asking here you looked up that error message?
if it does load and appear to run and if you have a debugger, you can stop the cpu and read 0x20000400 and should see the 0x12345678 written by the program as further confirmation that the program did load and run. Then examine my makefile, linker script and where it is used in the compile process, vs yours.
If you are trying to call all of the toolchain by using gcc then there are additional things you need to know, something like
arm-whatever-gcc other flags, -Xlinker '-T flash.ld' flash.s so.c -o so.elf
basically one or two -Xlinker or whatever the correct command line option is I think I use one -Xlinker for every ld option (-Xlinker -T -Xlinker flash.ld, but YMMV, I pretty much never have gcc do this extra work if I can avoid it prefer to call them directly, I let gcc call the assembler to make the compiled output an object, but other than that...). Just running gcc without options gives you the first level help then from that they show other things you can get help on and dig down (like passing parameters to the linker or assembler).