Scenario:
I've taken over some prototyping development work on a Coldfire evaluation board. I'm new to this kind of embedded stuff, although covered a little at uni (I finished 6 years ago) - but to be honest, it's not in my head at the moment - given a little pointers it might bring it all back. I've done plenty of C, C++, C# development for Windows and set-top-boxes - but usually the tools I've used have made all the base project for me - not needing to worry about things other than the application logic and memory/hardware constraints.
I have a very simple app working at the moment written by another guy who's unavailable to assist.
I'm using GNU gcc (m68k port) within Cygwin for development. The application compiles fine - but I'm unsure about some of the ancillary files in the project.
I have a single .c file, a number of .h files, a makefile and three unknown (assuming assembler or something) files. I'm not using any external libraries (-nostdlib) as I have none.
The unknown files are named:
api.lds api.lds.S apicrt0.S
The contents of api.lds and api.lds.S are almost identical, with only the 4th line (and minor formatting/comment changes) being different, the api.lds file is:
ENTRY(_start) SECTIONS { . = BASE_ADDRESS;
_img_start = .;
.text : { *(.text) } .data : { *(.data) } .rodata : { *(.rodata*) . = ALIGN(4); /* Align the end of rodata. */ } .glue : { *(.glue*) }
_text = ADDR(.text); _etext = ADDR(.rodata) + SIZEOF(.rodata);
_img_end = .;
.bss : { *(.bss) } _bss = ADDR(.bss); _ebss = ADDR(.bss) + SIZEOF(.bss);
. = ALIGN(4);
_stack = .; . = . + (16 * 1024); _estack = .;
.sizealign (NOLOAD) : { } = 0x0 }
The difference with the api.lds.S file is that the 4th line is: . = BASE_ADDRESS;
The other file, apicrt0.S contains:
.global _start .extern _estack, _bss, _ebss .align 4
/* * The following defines the registers that are * maintained by the debugger. */ .equ r_d0,0 .equ r_d1,4 .equ r_d2,8 .equ r_d3,12 .equ r_d4,16 .equ r_d5,20 .equ r_d6,24 .equ r_d7,28 .equ r_a0,32 .equ r_a1,36 .equ r_a2,40 .equ r_a3,44 .equ r_a4,48 .equ r_a5,52 .equ r_a6,56 .equ r_sp,60 .equ r_pc,64 .equ r_sr,68 .equ r_sz,72 _start: /* save registers to stack */ //movem.l %d0-%d7/%a0-%a6,(r_d0-r_sz,%sp) move.l %d0 , (r_d0-r_sz,%sp) move.l %d1 , (r_d1-r_sz,%sp) move.l %d2 , (r_d2-r_sz,%sp) move.l %d3 , (r_d3-r_sz,%sp) move.l %d4 , (r_d4-r_sz,%sp) move.l %d5 , (r_d5-r_sz,%sp) move.l %d6 , (r_d6-r_sz,%sp) move.l %d7 , (r_d7-r_sz,%sp) move.l %a0 , (r_a0-r_sz,%sp) move.l %a1 , (r_a1-r_sz,%sp) move.l %a2 , (r_a2-r_sz,%sp) move.l %a3 , (r_a3-r_sz,%sp) move.l %a4 , (r_a4-r_sz,%sp) move.l %a5 , (r_a5-r_sz,%sp) move.l %a6 , (r_a6-r_sz,%sp) move.l %sp, (r_sp-r_sz, %sp) /* sp */ move.l 4(%sp),(r_pc-r_sz, %sp) /* pc */ move.w 2(%sp),(r_sr-r_sz, %sp) /* sr */ move.w 2(%sp),(r_sr+2-r_sz, %sp) /* sr */ /* Decrement Stack pointer by size of regs */ move.l %sp, %d0 subi.l #r_sz, %d0 move.l %d0, %sp /* zero the bss */ move.l #_bss, %A1 move.l #_ebss, %A2 bss_zero_loop: cmpa.l %A2, %A1 bge bss_zero_end move.l #0, (%A1)+ bra bss_zero_loop bss_zero_end:
/* save old & load new stack pointer */ move.l #saved_sp, %A1 move.l %sp, (%A1) move.l #_estack, %A1 move.l %A1, %sp
/* call main */ jsr main
move.l #saved_sp, %A1 move.l (%A1), %sp
/* Increment Stack pointer by size of regs */ move.l %sp, %d0 addi.l #r_sz, %d0 move.l %d0, %sp /* reload previous registers */ //movem.l (r_d0-r_sz,%sp),%d0-%d7/%a0-%a6 move.l (r_d0-r_sz,%sp),%d0 move.l (r_d1-r_sz,%sp),%d1 move.l (r_d2-r_sz,%sp),%d2 move.l (r_d3-r_sz,%sp),%d3 move.l (r_d4-r_sz,%sp),%d4 move.l (r_d5-r_sz,%sp),%d5 move.l (r_d6-r_sz,%sp),%d6 move.l (r_d7-r_sz,%sp),%d7
move.l (r_a0-r_sz,%sp),%a0 move.l (r_a1-r_sz,%sp),%a1 move.l (r_a2-r_sz,%sp),%a2 move.l (r_a3-r_sz,%sp),%a3 move.l (r_a4-r_sz,%sp),%a4 move.l (r_a5-r_sz,%sp),%a5 move.l (r_a6-r_sz,%sp),%a6
nop rts nop nop saved_sp: .long 0x00000000
.end
I'm guessing that they're assembler code to do the initialisation etc (_start). However, can someone explain the difference between the two files, and how they're built etc? Could one of the api.lds/api.lds.S files be historical/obsolete?
The Makefile contains:
export SHELL=/bin/bash BOOTROOT=$(shell pwd)
# **************************** # Set up required definitions # **************************** CONFIG_APP_OFFSET=0x00100000 BUILD_SDRAM_BASE=0x00000000 BUILD_FLASH_BASE=0xFF800000 BUILD_LOCATION=RAM
AR=m68k-elf-ar AS=m68k-elf-as CC=m68k-elf-gcc CPP=m68k-elf-cpp CXX=m68k-elf-g++ LD=m68k-elf-ld OBJCOPY=m68k-elf-objcopy OBJDUMP=m68k-elf-objdump STRIP=m68k-elf-strip
DEFINES = -DBASE_ADDRESS=$(BUILD_SDRAM_BASE)+$(CONFIG_APP_OFFSET) \ -DMEMAP_BASE_SDRAM=$(BUILD_SDRAM_BASE) \ -DBOOTFLASH_PHYS_BASE=$(BUILD_FLASH_BASE) \ -DLOGIC_CARDENGINE_MCF5475_10 -DCONFIG_IN_FLASH=0 -DM5475EVB
ASFLAGS = -m5407 -D_ASM_ $(INCLUDES) $(DEFINES)
CFLAGS = -m5407 -malign-int -mnoshort -mstrict-align -fno-builtin \ -O0 -Wall -g -ggdb $(INCLUDES) $(DEFINES) -fno-builtin \ -nostdlib -N
LFLAGS = $(DEFINES) $(INCLUDES) -preproc
LDSFLAGS = -T api.lds
# ********************************** # Set up application to be complied # ********************************** EXECUTABLE=appname SOURCES=appname.c OBJECTS=appname.o apicrt0.o
# ************************************** # the default target for our make files # **************************************
all: clean $(SOURCES) $(EXECUTABLE)
$(EXECUTABLE): $(OBJECTS) $(CC) $(CFLAGS) $(LDFLAGS) $(LDSFLAGS) $(OBJECTS) -o $@.elf cp $@.elf $@.debug $(STRIP) $@.elf $(OBJCOPY) -O binary $(EXECUTABLE).elf $(EXECUTABLE).raw .c.o: $(CC) -c $(CFLAGS) $< -o $@ .lds: $(CPP) -P -D_ASM_ $(DEFINES) $(INCLUDES) $< > $@ clean:: -rm *.o *.raw *.elf *.debug
From this I suspect that it's using appname.c, apicrt0.S, and api.lds (ignoring api.lds.S entirely.
So, if I needed to move the source files into another compiler/IDE (eg. Eclipse with Zylin CDT for embedded work) then I don't need any other files than appname.c, apicrt0.S and api.lds - right?
What's the difference between the api.lds and apicrt0.S files?
Sorry if all this is a bit basic - I've got some more questions which I'll put into another post another time!
Thanks for your help,
David