|
|
  |
GNU-сный math |
|
|
|
Mar 30 2012, 21:24
|
Гуру
     
Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322

|
Добрый вечер. Создал проект для GCC Cortex-M3. Проект содержит только функцию main следующего содержания Код #include "efm32g890f128.h" #include <math.h>
volatile float DeltaX=50, DeltaY=120, Angle=3.14/4; volatile float Delta; volatile unsigned char DistanceFlag; int main() { while (1) { float dx=DeltaX, dy=DeltaY, angle=Angle, distance_delta; dx=dx*cos(angle); distance_delta=dx*dx+dy*dy; distance_delta=sqrt(distance_delta); if (distance_delta>100) DistanceFlag=1; Delta=distance_delta; } } Получил на выходе Код 10416 1092 264 11772 2dfc ./exe/efm_cpp_main.axf Что так много-то? Запустил elf в Keil. Цикл while выполнился за ~3500 тактов, если Keil мне не врёт. Makefile: CODE #+--------------------------------------------------------------------------- # # Copyright © 2010 Anton Gusev aka AHTOXA (HTTP://AHTOXA.NET) # # File: makefile # # Contents: makefile to build arm Cortex-M3 software with gcc # #----------------------------------------------------------------------------
############# program name TARGET = efm_cpp_main
# program version VER_MAJOR = 0 VER_MINOR = 1
TOOL = arm-none-eabi- # TOOL = arm-kgp-eabi-
# compile options MCU = cortex-m3 OPTIMIZE = -O3 USE_LTO = NO
# Select family # STM32F10X_LD : STM32 Low density devices # STM32F10X_LD_VL : STM32 Low density Value Line devices # STM32F10X_MD : STM32 Medium density devices # STM32F10X_MD_VL : STM32 Medium density Value Line devices # STM32F10X_HD : STM32 High density devices # STM32F10X_HD_VL : STM32 XL-density devices # STM32F10X_CL : STM32 Connectivity line devices # STM32F10X_XL : STM32G890 XL-density devices CHIP = EFM32G890
#defines DEFS = -D$(CHIP) DEFS += -DVER_MAJOR=$(VER_MAJOR) DEFS += -DVER_MINOR=$(VER_MINOR)
########################################################### # common part for all my cortex-m3 projects ###########################################################
BASE = . CC = $(TOOL)gcc CXX = $(TOOL)g++ LD = $(TOOL)g++ AS = $(CC) -x assembler-with-cpp OBJCOPY = $(TOOL)objcopy OBJDUMP = $(TOOL)objdump SIZE = $(TOOL)size -d FLASHER = openocd RM = rm -f CP = cp MD = mkdir
# dirs SRCDIR = $(BASE)/src OBJDIR = $(BASE)/obj EXEDIR = $(BASE)/exe LSTDIR = $(BASE)/lst PRJDIR = $(BASE)/prj BAKDIR = $(BASE)/bak
#files HEX = $(EXEDIR)/$(TARGET).hex BIN = $(EXEDIR)/$(TARGET).bin ELF = $(EXEDIR)/$(TARGET).axf MAP = $(LSTDIR)/$(TARGET).map LSS = $(LSTDIR)/$(TARGET).lss OK = $(EXEDIR)/$(TARGET).ok
# linker script (chip dependent) LD_SCRIPT = $(PRJDIR)/$(CHIP).ld
# source directories (all *.c, *.cpp and *.S files included) DIRS := $(SRCDIR) DIRS += $(COMMON)
# includes INCS := $(patsubst %, -I "%", $(DIRS))
# individual source files SRCS :=
#calc obj files list OBJS := $(SRCS) OBJS += $(wildcard $(addsuffix /*.cpp, $(DIRS))) OBJS += $(wildcard $(addsuffix /*.c, $(DIRS))) OBJS += $(wildcard $(addsuffix /*.S, $(DIRS))) OBJS := $(notdir $(OBJS)) OBJS := $(OBJS:.cpp=.o) OBJS := $(OBJS:.c=.o) OBJS := $(OBJS:.S=.o) OBJS := $(patsubst %, $(OBJDIR)/%, $(OBJS))
#files to archive ARCFILES = \ $(SRCDIR) \ $(PRJDIR) \ $(BASE)/makefile \ $(BASE)/.cproject \ $(BASE)/.project
# flags FLAGS = -mcpu=$(MCU) -mthumb FLAGS += $(INCS) FLAGS += -MD FLAGS += $(DEFS) FLAGS += -Wa,-adhlns=$(addprefix $(LSTDIR)/, $(notdir $(addsuffix .lst, $(basename $<))))
AFLAGS = $(FLAGS)
CFLAGS = $(FLAGS) CFLAGS += $(OPTIMIZE) CFLAGS += -std=gnu99 CFLAGS += -g CFLAGS += -ffunction-sections -fdata-sections CFLAGS += -Wall -Wextra CFLAGS += -Wimplicit -Wcast-align -Wpointer-arith -Wredundant-decls CFLAGS += -Wshadow -Wcast-qual -Wcast-align -Wnested-externs -pedantic
CXXFLAGS = $(FLAGS) CXXFLAGS += $(OPTIMIZE) CXXFLAGS += -g CXXFLAGS += -fno-exceptions -fno-rtti CXXFLAGS += -ffunction-sections -fdata-sections CXXFLAGS += -fno-threadsafe-statics CXXFLAGS += -funsigned-bitfields -fshort-enums CXXFLAGS += -Wall -Wextra CXXFLAGS += -Winline CXXFLAGS += -Wpointer-arith -Wredundant-decls CXXFLAGS += -Wshadow -Wcast-qual -Wcast-align -pedantic
LD_FLAGS = -mcpu=$(MCU) LD_FLAGS += -mthumb LD_FLAGS += -nostartfiles LD_FLAGS += -Wl,-Map="$(MAP)",--cref LD_FLAGS += -Wl,--gc-sections LD_FLAGS += -T$(LD_SCRIPT)
ifeq ($(USE_LTO),YES) CFLAGS += -flto CXXFLAGS += -flto LD_FLAGS += -flto $(OPTIMIZE) endif
#openocd command-line
# debug level (d0..d3) oocd_params = -d0 # interface and board/target settings (using the OOCD target-library here) # oocd_params += -c "fast enable" oocd_params += -f interface/arm-usb-ocd.cfg oocd_params += -f board/stm32f10x_128k_eval.cfg oocd_params += -c init -c targets oocd_params_program = $(oocd_params) # commands to prepare flash-write oocd_params_program += -c "halt" # flash-write and -verify oocd_params_program += -c "flash write_image erase $(ELF)" oocd_params_program += -c "verify_image $(ELF)" # reset target oocd_params_program += -c "reset run" # terminate OOCD after programming oocd_params_program += -c shutdown
oocd_params_reset = $(oocd_params) oocd_params_reset += -c "reset run" oocd_params_reset += -c shutdown
.SILENT :
.PHONY: all start dirs build clean program reset archive
############# targets
all : start dirs $(ELF) $(BIN) $(LSS) $(OK)
build: clean all
start: @echo --- building $(TARGET)
$(LSS): $(ELF) makefile @echo --- making asm-lst... # @$(OBJDUMP) -dStC $(ELF) > $(LSS) @$(OBJDUMP) -dC $(ELF) > $(LSS)
$(OK): $(ELF) @$(SIZE) $(ELF) @echo "Errors: none"
$(ELF): $(OBJS) makefile @echo --- linking... $(LD) $(OBJS) $(LIBS) $(LD_FLAGS) -o "$(ELF)"
$(HEX): $(ELF) @echo --- make hex... @$(OBJCOPY) -O ihex $(ELF) $(HEX)
$(BIN): $(ELF) @echo --- make binary... @$(OBJCOPY) -O binary $(ELF) $(BIN)
program: $(ELF) @echo "Programming with OPENOCD" $(FLASHER) $(oocd_params_program)
reset: @echo Resetting device $(FLASHER) $(oocd_params_reset)
VPATH := $(DIRS)
$(OBJDIR)/%.o: %.cpp makefile @echo --- compiling $<... $(CXX) -c $(CXXFLAGS) -o $@ $<
$(OBJDIR)/%.o: %.c makefile @echo --- compiling $<... $(CC) -c $(CFLAGS) -o $@ $<
$(OBJDIR)/%.o: %.S makefile @echo --- assembling $<... $(AS) -c $(AFLAGS) -o $@ $<
dirs: $(OBJDIR) $(EXEDIR) $(LSTDIR) $(BAKDIR)
$(OBJDIR): -@$(MD) $(OBJDIR)
$(EXEDIR): -@$(MD) $(EXEDIR)
$(LSTDIR): -@$(MD) $(LSTDIR)
$(BAKDIR): -@$(MD) $(BAKDIR)
clean: -@$(RM) $(OBJDIR)/*.d 2>/dev/null -@$(RM) $(OBJDIR)/*.o 2>/dev/null -@$(RM) $(LSTDIR)/*.lst 2>/dev/null -@$(RM) $(ELF) -@$(RM) $(HEX) -@$(RM) $(LSS) -@$(RM) $(MAP)
archive: @echo --- archiving... 7z a $(BAKDIR)/$(TARGET)_`date +%Y-%m-%d,%H-%M-%S` $(ARCFILES) @echo --- done!
# dependencies ifeq (,$(findstring build,$(MAKECMDGOALS))) ifeq (,$(findstring clean,$(MAKECMDGOALS))) ifeq (,$(findstring dirs,$(MAKECMDGOALS))) -include $(wildcard $(OBJDIR)/*.d) endif endif endif
Toolchain: Yagarto. Чтобы в нём поменять?
efm_cpp_main.rar ( 278.03 килобайт )
Кол-во скачиваний: 100P.S. Из интереса создал точно такой же проект в AtmelStudio6 для xmega128A1. Запустил AVRStudio 4.18. Цикл while выполнился за 2900 тактов.
efm_cpp_main.rar ( 278.03 килобайт )
Кол-во скачиваний: 100
|
|
|
|
|
Apr 2 2012, 11:11
|
Гуру
     
Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322

|
Цитата(klen @ Apr 2 2012, 07:49)  а в чем проблема то? В размере программы. Цитата(klen @ Apr 2 2012, 07:49)  плавучка на M3 програмная. вот и кода много и цыкл длинный На АВР тоже FPU нет: Код Task "RunCompilerTask" C:\Program Files\Atmel\Atmel Studio 6.0\make\make.exe clean all rm -rf test_math.o test_math.d rm -rf "test_math.hex" "test_math.lss" "test_math.eep" "test_math.map" test_math.cpp Invoking: AVR8/GNU C++ Compiler "C:\Program Files\Atmel\Atmel Studio 6.0\extensions\Atmel\AVRGCC\3.3.2.31\AVRToolchain\bin\avr-g++.exe" -funsigned-char -funsigned-bitfields -O1 -fpack-struct -fshort-enums -g2 -Wall -c -MD -MP -MF "test_math.d" -MT"test_math.d" -mmcu=atxmega128a1 -o"test_math.o" ".././test_math.cpp" Finished building: .././test_math.cpp Building target: test_math.elf Invoking: AVR8/GNU C++ Linker "C:\Program Files\Atmel\Atmel Studio 6.0\extensions\Atmel\AVRGCC\3.3.2.31\AVRToolchain\bin\avr-g++.exe" -o test_math.elf test_math.o -Wl,-Map="test_math.map" -Wl,--start-group -Wl,-lm -Wl,--end-group -mmcu=atxmega128a1 Finished building target: test_math.elf "C:\Program Files\Atmel\Atmel Studio 6.0\extensions\Atmel\AVRGCC\3.3.2.31\AVRToolchain\bin\avr-objcopy.exe" -O ihex -R .eeprom -R .fuse -R .lock -R .signature "test_math.elf" "test_math.hex" "C:\Program Files\Atmel\Atmel Studio 6.0\extensions\Atmel\AVRGCC\3.3.2.31\AVRToolchain\bin\avr-objcopy.exe" -j .eeprom --set-section-flags=.eeprom=alloc,load --change-section-lma .eeprom=0 --no-change-warnings -O ihex "test_math.elf" "test_math.eep" || exit 0 "C:\Program Files\Atmel\Atmel Studio 6.0\extensions\Atmel\AVRGCC\3.3.2.31\AVRToolchain\bin\avr-objdump.exe" -h -S "test_math.elf" > "test_math.lss" "C:\Program Files\Atmel\Atmel Studio 6.0\extensions\Atmel\AVRGCC\3.3.2.31\AVRToolchain\bin\avr-size.exe" -C --mcu=atxmega128a1 "test_math.elf" AVR Memory Usage ---------------- Device: atxmega128a1 Program: 1848 bytes (1.3% Full) (.text + .data + .bootloader) Data: 17 bytes (0.2% Full) (.data + .bss + .noinit) А вот для cortex: Код text data bss dec hex filename 10448 1092 264 11804 2e1c ./exe/efm_cpp_main.axf Что для 0, что для 3 - примерно одинаково. Цитата(klen @ Apr 2 2012, 07:49)  2. в libm из которой у Вас линкуется sqrt и cos сответствует стандарту со всеми ненужными вещами (проверки на диапазон, NAN, OVF, и тд) - сделайте свои быстрые реализации основываясь на статистике Ваших входных данных. Свои можно. Цитата(klen @ Apr 2 2012, 07:49)  3. тупо поменяйте на микросхемку с ядром M4F - реальный пруфф! Пруфф для STMicro? А мне то что с того? Цитата(klen @ Apr 2 2012, 07:49)  ps. это вы уважаймый еще float a =.... ; printf ("%f", a ) не пробвали  Не пробовал, но - верю: результат будет ужасен и невпихуем.
|
|
|
|
|
Apr 2 2012, 19:28
|
Гуру
     
Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322

|
Цитата(ReAl @ Apr 2 2012, 21:05)  На AVR еще и double нет, double эквивалентен float. А у Вас в коде и float используется, и double-арифметика подтягивается для cos, sqrt — итого двойной комплект. Кстати да. Цитата(ReAl @ Apr 2 2012, 21:05)  Попробуйте cosf(), sqrtf(), может, станет поменьше. Исходно: Цитата 10456 1092 264 11812 2e24 ./exe/efm_cpp_main.axf float заменил на double Цитата text data bss dec hex filename 8840 1104 272 10216 27e8 ./exe/efm_cpp_main.axf вернул float, cos заменил на cosf, sqrt на sqrtf Цитата text data bss dec hex filename 9176 1092 264 10532 2924 ./exe/efm_cpp_main.axf Помогает, но слабо. Можно конечно косинус затабулировать. Корень целочисленный использовать.
|
|
|
|
|
Apr 14 2012, 17:35
|
Местный
  
Группа: Участник
Сообщений: 313
Регистрация: 2-07-11
Пользователь №: 66 023

|
Цитата(_Артём_ @ Apr 2 2012, 23:28)  float заменил на double
вернул float, cos заменил на cosf, sqrt на sqrtf То что с double короче чем с cosf, sqrtf наводит на мысль что в последнем случае double арифметика всё равно используется где-то. Можно посмотреть дизассемблерный листинг (.lss обычно), там в конце будут функции обработки чисел с плавающей точкой. Сложение double - функция __adddf3, float - функция __addsf3, и аналогично для других операций - с буквой "d" или "f" в имени соответственно. Можно проследить откуда вызываются double операции. За сколько тактов выполняется цикл с cosf и sqrtf?
|
|
|
|
|
Apr 14 2012, 18:51
|
Гуру
     
Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322

|
Цитата(maksimp @ Apr 14 2012, 20:35)  То что с double короче чем с cosf, sqrtf наводит на мысль что в последнем случае double арифметика всё равно используется где-то. Можно посмотреть дизассемблерный листинг (.lss обычно), там в конце будут функции обработки чисел с плавающей точкой. Сложение double - функция __adddf3, float - функция __addsf3, и аналогично для других операций - с буквой "d" или "f" в имени соответственно. Можно проследить откуда вызываются double операции. Функции __aeabi_dmul, __adddf3 и другие присутствуют. В понедельник попробую проследить зачем и кто их вызывает. Цитата(maksimp @ Apr 14 2012, 20:35)  За сколько тактов выполняется цикл с cosf и sqrtf? Такты не считал, тому что размер не удовлетворяет совершенно.
|
|
|
|
|
May 23 2012, 14:05
|
Гуру
     
Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322

|
Цитата(glonium @ May 23 2012, 16:58)  Наступил на похожие грабли, потом добавил флаги -ffunction-section к компилятору и -Xlinker --gc-sections к компоновщику выкинул кучу мусора из бинарника и размер кода сократился со 100 до 5 Кб! Вряд ли это поможет. Из makefile: CODE AFLAGS = $(FLAGS)
CFLAGS = $(FLAGS) CFLAGS += $(OPTIMIZE) CFLAGS += -std=gnu99 CFLAGS += -g3 CFLAGS += -ffunction-sections -fdata-sections CFLAGS += -Wall -Wextra CFLAGS += -Wimplicit -Wcast-align -Wpointer-arith -Wredundant-decls CFLAGS += -Wshadow -Wcast-qual -Wcast-align -Wnested-externs #-pedantic
CXXFLAGS = $(FLAGS) CXXFLAGS += $(OPTIMIZE) CXXFLAGS += -g3 CXXFLAGS += -fno-exceptions -fno-rtti CXXFLAGS += -ffunction-sections -fdata-sections CXXFLAGS += -fno-threadsafe-statics CXXFLAGS += -funsigned-bitfields -fshort-enums CXXFLAGS += -Wall -Wextra CXXFLAGS += -Winline CXXFLAGS += -Wpointer-arith -Wredundant-decls CXXFLAGS += -Wshadow -Wcast-qual -Wcast-align --fast-math #-pedantic
LD_FLAGS = -mcpu=$(MCU) LD_FLAGS += -mthumb LD_FLAGS += -nostartfiles LD_FLAGS += -Wl,-Map="$(MAP)",--cref LD_FLAGS += -Wl,--gc-sections LD_FLAGS += -T$(LD_SCRIPT)
Сообщение отредактировал IgorKossak - May 23 2012, 14:36
Причина редактирования: [codebox]
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|