From 5fe80dd99d51e317e3b05f2715978fca16723f60 Mon Sep 17 00:00:00 2001 From: salvopitru Date: Wed, 15 Dec 2010 11:10:20 +0000 Subject: [PATCH] Added elfloader machine dependent code for STM32W. --- cpu/stm32w108/Makefile.stm32w108 | 95 +++++++++--- cpu/stm32w108/elfloader-arch.c | 141 ++++++++++++++++++ .../hal/micro/cortexm3/stm32w108/gnu.ld | 30 ++-- 3 files changed, 230 insertions(+), 36 deletions(-) create mode 100644 cpu/stm32w108/elfloader-arch.c diff --git a/cpu/stm32w108/Makefile.stm32w108 b/cpu/stm32w108/Makefile.stm32w108 index b1bb6c4d8..992899324 100644 --- a/cpu/stm32w108/Makefile.stm32w108 +++ b/cpu/stm32w108/Makefile.stm32w108 @@ -16,7 +16,7 @@ CONTIKI_CPU=$(CONTIKI)/cpu/stm32w108 CONTIKI_CPU_DIRS = . dev hal simplemac hal/micro/cortexm3 hal/micro/cortexm3/stm32w108 -STM32W_C = leds-arch.c leds.c clock.c watchdog.c uart1.c uart1-putchar.c slip_uart1.c \ +STM32W_C = leds-arch.c leds.c clock.c watchdog.c uart1.c uart1-putchar.c slip_uart1.c slip.c\ stm32w-radio.c stm32w_systick.c uip_arch.c rtimer-arch.c adc.c micro.c sleep.c \ micro-common.c micro-common-internal.c clocks.c mfg-token.c nvm.c flash.c rand.c @@ -29,6 +29,11 @@ else STM32W_C += crt_stm32w108.c endif +ifdef ELF_LOADER +ELFLOADER = elfloader-arch.c symtab.c +endif + + # .s and .s79 not specified here because in Makefile.include only .c and .S suffixes are replaced with .o. CONTIKI_TARGET_SOURCEFILES += $(STM32W_C) \ $(SYSAPPS) $(ELFLOADER) \ @@ -55,7 +60,9 @@ AS = iasmarm AR = iarchive OBJCOPY = ielftool STRIP = strip +ifndef DEBUG OPTI = -Ohz --no_unroll +endif CFLAGSNO = --endian=little --cpu=Cortex-M3 -e --diag_suppress Pa050 -D BOARD_HEADER=\"board.h\" \ -D BOARD_MB851 -D "PLATFORM_HEADER=\"hal/micro/cortexm3/compiler/iar.h\"" -D CORTEXM3 \ -D CORTEXM3_STM32W108 -D PHY_STM32W108XX -D DISABLE_WATCHDOG -D ENABLE_ADC_EXTENDED_RANGE_BROKEN \ @@ -73,14 +80,18 @@ OBJOPTS = --bin else # GCC -CC = arm-none-eabi-gcc +CC = arm-none-eabi-gcc LD = arm-none-eabi-gcc -AS = arm-none-eabi-gcc +AS = arm-none-eabi-gcc +NM = arm-none-eabi-nm AR = arm-none-eabi-ar OBJCOPY = arm-none-eabi-objcopy STRIP = arm-none-eabi-strip -SIZE = arm-none-eabi-size -OPTI = -Os -ffunction-sections -fshort-enums +SIZE = arm-none-eabi-size +ifndef DEBUG +OPTI = -Os -ffunction-sections +endif + CFLAGSNO = -mthumb -mcpu=cortex-m3 -fsigned-char -D "PLATFORM_HEADER=\"hal/micro/cortexm3/compiler/gnu.h\"" \ -D BOARD_HEADER=\"board.h\" -g -Wall -Wno-strict-aliasing -mlittle-endian \ -D BOARD_MB851 -D CORTEXM3 -D CORTEXM3_STM32W108 -D PHY_STM32W108XX -D DISABLE_WATCHDOG -D ENABLE_ADC_EXTENDED_RANGE_BROKEN \ @@ -94,27 +105,34 @@ LDFLAGS += -mcpu=cortex-m3 \ -Wl,-static \ -u Default_Handler \ -nostartfiles \ - -Wl,-Map -Xlinker contiki-$(TARGET).map \ - -Wl,--gc-sections + -Wl,-Map -Xlinker contiki-$(TARGET).map + +ifndef ELF_LOADER + # Do not use garbage collection when the elfloader is used. + LDFLAGS += -Wl,--gc-sections +endif + SIZEFLAGS = -A OBJOPTS = -O binary endif -ifdef COFFEE_FILES #if files are defined force definition of COFFEE_ADDRESS - ifndef COFFEE_ADDRESS - COFFEE_ADDRESS=0x8010000 - endif - COFFEE_ADDRESS1 = $(shell echo $$(( $(COFFEE_ADDRESS) + 1 ))) - CONTIKI_TARGET_SOURCEFILES += cfs-coffee.c cfs-coffee-arch.c - CFLAGS += -DCOFFEE_FILES=$(COFFEE_FILES) -DCOFFEE_ADDRESS=$(COFFEE_ADDRESS) - ifdef IAR - LDFLAGS+= --config $(CONTIKI_CPU)/hal/micro/cortexm3/stm32w108/iar-cfg-coffee.icf - else - LDFLAGS+= -Wl,--section-start=.coffeefiles=$(COFFEE_ADDRESS) - endif +ifndef IAR +ifdef COFFEE_ADDRESS + COFFEE = 1 +endif + +# Default values for coffee section start. +ifndef COFFEE_ADDRESS + COFFEE_ADDRESS = 0x8010c00 +endif + +ifeq ($(COFFEE),1) + CONTIKI_TARGET_SOURCEFILES += cfs-coffee.c cfs-coffee-arch.c + CFLAGS += -DCOFFEE_ADDRESS=$(COFFEE_ADDRESS) + #If $make invokation passed starting address use phony target to force synchronization of source to .coffeefiles section #Warning: recompilation will not be forced if the starting address is then dropped, with dire consequences: # -->Source that uses COFFEE_FILES and read macros for conditional compilation will be left hanging! @@ -127,11 +145,24 @@ ifdef COFFEE_FILES #if files are defined force definition of COFF $(OBJECTDIR)/cfs-coffee-arch.o : coffee #cfs-coffee-arch uses COFFEE_FILES, COFFEE_ADDRESS $(OBJECTDIR)/cfs-coffee.o : coffee #core routine requires recompilation -#endif -#endif - +else + # Coffee starts at the end of the flash, before NVM section. + COFFEE_ADDRESS = 0x801F400 endif +LDFLAGS+= -Wl,--section-start=.coffee=$(COFFEE_ADDRESS) + +else #IAR + + ifeq ($(COFFEE),1) + LDFLAGS+= --config $(CONTIKI_CPU)/hal/micro/cortexm3/stm32w108/iar-cfg-coffee.icf + endif + +endif + + + + FLASHER = $(CONTIKI)/tools/stm32w/stm32w_flasher/linux/stm32w_flasher # Check if we are running under Windows @@ -172,6 +203,7 @@ else SEDCOMMAND = sed -e '1s,\($(OBJECTDIR)\\$*\)\.o:,\1.o : ,g' -e '1!s,\($(OBJECTDIR)\\$*\)\.o:, ,g' -e 's,\\\([^ ]\),/\1,g' -e 's,$$, \\,' -e '$$s, \\$$,,' < $(@:.o=.P) > $(@:.o=.d) endif + CUSTOM_RULE_C_TO_OBJECTDIR_O = 1 $(OBJECTDIR)/%.o: %.c $(CC) $(CFLAGS) $< --dependencies=m $(@:.o=.P) -o $@ @@ -183,9 +215,26 @@ CUSTOM_RULE_C_TO_CO = 1 $(CC) $(CFLAGS) -DAUTOSTART_ENABLE $< -o $@ else #IAR +CUSTOM_RULE_C_TO_CE = 1 +%.ce: %.c + $(CC) $(CFLAGS) -fno-merge-constants -fno-function-sections -DAUTOSTART_ENABLE -c $< -o $@ + $(STRIP) --strip-unneeded -g -x $@ + CUSTOM_RULE_LINK = 1 -%.$(TARGET): %.co $(PROJECT_OBJECTFILES) $(PROJECT_LIBRARIES) contiki-$(TARGET).a +.PHONY: symbols.c symbols.h +ifdef CORE +ifeq ($(wildcard $(CORE)),) + ${error $(CORE) doesn't exist} +endif +symbols.c: + $(NM) $(CORE) | awk -f $(CONTIKI)/tools/mknmlist > symbols.c +else +symbols.c symbols.h: + @$(CONTIKI)/tools/make-empty-symbols +endif + +%.$(TARGET): %.co $(PROJECT_OBJECTFILES) $(PROJECT_LIBRARIES) contiki-$(TARGET).a $(OBJECTDIR)/symbols.o $(LD) $(LDFLAGS) $(TARGET_STARTFILES) ${filter-out %.a,$^} -Wl,-\( ${filter %.a,$^} $(TARGET_LIBFILES) -Wl,-\) -o $@ @echo >> contiki-$(TARGET).map @$(SIZE) $(SIZEFLAGS) $@ >> contiki-$(TARGET).map diff --git a/cpu/stm32w108/elfloader-arch.c b/cpu/stm32w108/elfloader-arch.c new file mode 100644 index 000000000..1b794b421 --- /dev/null +++ b/cpu/stm32w108/elfloader-arch.c @@ -0,0 +1,141 @@ +#include "contiki.h" +#include "elfloader-arch.h" +#include "cfs-coffee-arch.h" + +#if 1 +#include +#define PRINTF(...) printf(__VA_ARGS__) +#else +#define PRINTF(...) do {} while (0) +#endif + +#define ELF32_R_TYPE(info) ((unsigned char)(info)) + +/* Supported relocations */ + +#define R_ARM_ABS32 2 +#define R_ARM_THM_CALL 10 + +/* Adapted from elfloader-arm.c */ + +static uint32_t datamemory_aligned[(ELFLOADER_DATAMEMORY_SIZE+3)/4]; //word aligned +static uint8_t* datamemory = (uint8_t *)datamemory_aligned; +VAR_AT_SEGMENT (static const uint16_t textmemory[ELFLOADER_TEXTMEMORY_SIZE/2],".elf_text") = {0}; //halfword aligned +/*---------------------------------------------------------------------------*/ +void * +elfloader_arch_allocate_ram(int size) +{ + if(size > sizeof(datamemory_aligned)){ + PRINTF("RESERVED RAM TOO SMALL\n"); + } + return datamemory; +} +/*---------------------------------------------------------------------------*/ +void * +elfloader_arch_allocate_rom(int size) +{ + if(size > sizeof(textmemory)){ + PRINTF("RESERVED FLASH TOO SMALL\n"); + } + return (void *)textmemory; +} +/*---------------------------------------------------------------------------*/ +#define READSIZE sizeof(datamemory_aligned) + +void elfloader_arch_write_rom(int fd, unsigned short textoff, unsigned int size, char *mem) +{ + int32u ptr; + int nbytes; + + cfs_seek(fd, textoff, CFS_SEEK_SET); + + cfs_seek(fd, textoff, CFS_SEEK_SET); + for(ptr = 0; ptr < size; ptr += READSIZE) { + + /* Read data from file into RAM. */ + nbytes = cfs_read(fd, (unsigned char *)datamemory, READSIZE); + + /* Write data to flash. */ + stm32w_flash_write((int32u)mem, datamemory, nbytes); + } +} +/*---------------------------------------------------------------------------*/ + + +void elfloader_arch_relocate(int fd, + unsigned int sectionoffset, + char *sectionaddr, + struct elf32_rela *rela, char *addr) +{ + unsigned int type; + + type = ELF32_R_TYPE(rela->r_info); + + cfs_seek(fd, sectionoffset + rela->r_offset, CFS_SEEK_SET); + +/* PRINTF("elfloader_arch_relocate: type %d\n", type); */ +/* PRINTF("Addr: %p, Addend: %ld\n", addr, rela->r_addend); */ + switch(type) { + case R_ARM_ABS32: + { + int32_t addend; + cfs_read(fd, (char*)&addend, 4); + addr += addend; + cfs_seek(fd, -4, CFS_SEEK_CUR); + cfs_write(fd,&addr,4); + //elfloader_output_write_segment(output,(char*) &addr, 4); + PRINTF("%p: addr: %p\n", sectionaddr +rela->r_offset, + addr); + } + break; + case R_ARM_THM_CALL: + { + uint16_t instr[2]; + int32_t offset; + char *base; + cfs_read(fd, (char*)instr, 4); + cfs_seek(fd, -4, CFS_SEEK_CUR); + /* Ignore the addend since it will be zero for calls to symbols, + and I can't think of a case when doing a relative call to + a non-symbol position */ + base = sectionaddr + (rela->r_offset + 4); + + if (((instr[1]) & 0xe800) == 0xe800) { + /* BL or BLX */ + if (((uint32_t)addr) & 0x1) { + /* BL */ + instr[1] |= 0x1800; + } else { +#if defined(__ARM_ARCH_4T__) + return ELFLOADER_UNHANDLED_RELOC; +#else + /* BLX */ + instr[1] &= ~0x1800; + instr[1] |= 0x0800; +#endif + } + } + /* Adjust address for BLX */ + if ((instr[1] & 0x1800) == 0x0800) { + addr = (char*)((((uint32_t)addr) & 0xfffffffd) + | (((uint32_t)base) & 0x00000002)); + } + offset = addr - (sectionaddr + (rela->r_offset + 4)); + PRINTF("elfloader-arm.c: offset %d\n", (int)offset); + if (offset < -(1<<22) || offset >= (1<<22)) { + PRINTF("elfloader-arm.c: offset %d too large for relative call\n", + (int)offset); + } + /* PRINTF("%p: %04x %04x offset: %d addr: %p\n", sectionaddr +rela->r_offset, instr[0], instr[1], (int)offset, addr); */ + instr[0] = (instr[0] & 0xf800) | ((offset>>12)&0x07ff); + instr[1] = (instr[1] & 0xf800) | ((offset>>1)&0x07ff); + cfs_write(fd,&instr,4); + //elfloader_output_write_segment(output, (char*)instr, 4); + /* PRINTF("cfs_write: %04x %04x\n",instr[0], instr[1]); */ + } + break; + + default: + PRINTF("elfloader-arm.c: unsupported relocation type %d\n", type); + } +} diff --git a/cpu/stm32w108/hal/micro/cortexm3/stm32w108/gnu.ld b/cpu/stm32w108/hal/micro/cortexm3/stm32w108/gnu.ld index 6762ece51..ad7042027 100644 --- a/cpu/stm32w108/hal/micro/cortexm3/stm32w108/gnu.ld +++ b/cpu/stm32w108/hal/micro/cortexm3/stm32w108/gnu.ld @@ -13,7 +13,7 @@ GROUP( These are used by the startup in order to allocate stacks for the different modes. */ -__Stack_Size = 0x400 ; +__Stack_Size = 0x500 ; PROVIDE ( _Stack_Size = __Stack_Size ) ; @@ -28,7 +28,6 @@ There will be a link error if there is not this amount of RAM free at the end. _Minimum_Stack_Size = 0x500 ; - /* this sends all unreferenced IRQHandlers to reset */ @@ -114,13 +113,24 @@ SECTIONS *(.rodata*) *(.glue_7) *(.glue_7t) - - . = ALIGN(4); + . = ALIGN(1024); + *(.elf_text) + . = ALIGN(1024); + /*. = ALIGN(4);*/ _etext = .; - /* This is used by the startup in order to initialize the .data secion */ + /* This is used by the startup in order to initialize the .data section */ _sidata = _etext; } >ROM_region + .coffee 0x08010000 : + { + _coffee_start = ABSOLUTE(.); + . = ALIGN(1024); + *(.coffeefiles) + . = ORIGIN(NVM_region) - _coffee_start; + } > ROM_region = 0x00 + + NVM (NOLOAD): { . = ALIGN(1024); @@ -136,12 +146,6 @@ SECTIONS . = ALIGN(4); } > FIB_region -/* - .FAT (NOLOAD): - { - KEEP(*(.FAT)) - } > FIB_region -*/ /* after that it's only debugging information. */ @@ -152,7 +156,7 @@ SECTIONS .data : AT ( _sidata ) { . = ALIGN(4); - /* This is used by the startup in order to initialize the .data secion */ + /* This is used by the startup in order to initialize the .data section */ _sdata = . ; *(.data) @@ -161,9 +165,9 @@ SECTIONS . = ALIGN(4); /* This is used by the startup in order to initialize the .data secion */ _edata = . ; + ASSERT(_sidata + SIZEOF(.data) < LOADADDR(.coffee), ".data section overflow in ROM"); } >RAM_region - /* This is the uninitialized data section */ .bss :