Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: GNU-сный math
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > Cредства разработки для МК > GNU/OpenSource средства разработки
_Артём_
Добрый вечер.
Создал проект для 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.
Чтобы в нём поменять?Нажмите для просмотра прикрепленного файла

P.S. Из интереса создал точно такой же проект в AtmelStudio6 для xmega128A1. Запустил AVRStudio 4.18.
Цикл while выполнился за 2900 тактов.
Нажмите для просмотра прикрепленного файла

klen
а в чем проблема то? плавучка на M3 програмная. вот и кода много и цыкл длинный, предлагаю дял ужатия как по времени иак и по скрости следующие меры:
1. исключить преобразование числовых типов в float и обратно - это бывает тяжелее чем всякие синусы. грубо говоря вся обработа в одном типе float.
2. в libm из которой у Вас линкуется sqrt и cos сответствует стандарту со всеми ненужными вещами (проверки на диапазон, NAN, OVF, и тд) - сделайте свои быстрые реализации основываясь на статистике Ваших входных данных.
3. тупо поменяйте на микросхемку с ядром M4F - реальный пруфф! sqrt и арифметические операции на FPU. если используете stm32 то просто перепаять + 2-3 ножки питания с кондерами.

ps. это вы уважаймый еще float a =.... ; printf ("%f", a ) не пробвали sm.gif
_Артём_
Цитата(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 ) не пробвали sm.gif

Не пробовал, но - верю: результат будет ужасен и невпихуем.
ReAl
На AVR еще и double нет, double эквивалентен float.
А у Вас в коде и float используется, и double-арифметика подтягивается для cos, sqrt — итого двойной комплект.
Попробуйте cosf(), sqrtf(), может, станет поменьше.
_Артём_
Цитата(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

Помогает, но слабо.
Можно конечно косинус затабулировать.
Корень целочисленный использовать.

_Артём_
Ни у кого ссылка на библиотеку fixed-point не завалялась?
А то google ничего путного не даёт?
maksimp
Цитата(_Артём_ @ 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?
_Артём_
Цитата(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?

Такты не считал, тому что размер не удовлетворяет совершенно.
glonium
Наступил на похожие грабли, потом добавил флаги -ffunction-section к компилятору и -Xlinker --gc-sections к компоновщику выкинул кучу мусора из бинарника и размер кода сократился со 100 до 5 Кб!
_Артём_
Цитата(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)
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.