Hejka,
robię właśnie przesiadkę projektu z kompilatora IAR'a do GCC'a i mam problem z przeniesieniem niektórych ustawień, konkretniej chodzi o nie wycinanie przez linker konkretnych, nieużywanych zmiennych globalnych wygenerowanych przez zewnętrzne narzędzie, zawierających informacje np. o dacie buildu, checksumie itp. które są potem w przypadku reklamacji odczytywane po uarcie przez podanie adresu pamięci flash (zatem zmienne w kodzie nie są wprost używane).
W IARze wystarczyło dodać do zmiennej parametr "ROOT" i zmienne były dołączane do pliku wynikowego (hex), tutaj napotkałem na problem.
W najprostszej postaci wziąłem przykładowy projekt w TrueStudio (domyślnie używam gcc'a w wersji 5/2016 + eclipse). Plik wygląda następująco:
kompilator buduje plik z następującymi parametrami (rozdzielone enterem dla czytelności):
Linker, nic odkrywczego:
W tej formie kompilator nie usuwa zmiennej (zrzut objdump'a z pliku main.o):
Po usunięciu __attribute__((used)) lub static, zmienna znika z pliku obiektu, co jest prawidłowe i zgodne z dokumentacją GCC'a .
Problem w tym, że pomimo nie usunięcia zmiennej w pliku obiektu przez kompilator, jest ona usuwana przez linker (prawdopodobnie z powodu opcji "-Wl,--gc-sections") i jest widoczna w sekcji "Discarded input sections" w pliku mapy:
Oczywiście można by dodać odczyt zmiennych do jakiejś bezużytecznej zmiennej albo wstawić chociażby "asm("" :: "m" (build_info)", ale tych zmiennych jest sporo i wolałbym uniknąć dodawania kolejnego skryptu, który wygeneruje mi funkcje "odczytującą" wszystkie zmienne, to zresztą mogłoby zabierać trochę cennego miejsca we flashu.
Próbowałem już:
1. Umieścić zmienne w konkretnej sekcji, czyli dodanie sekcji w skrypcie linkera, do tego wewnątrz umieścić ją wewnątrz KEEP, czyli np. KEEP(*(.my_section)) + __attribute__((section(".my_section"))). Jeśli zmienna jest użyta, jest prawidłowo dodawana do sekcji na zadanym adresie.
2. Kombinowanie z opcjami "-ffunction-sections -fdata-sections " dla kompilatora i "-Wl,--gc-sections ", ale ich wyłączenie daje tylko nakładanie się sekcji (nic nie jest usuwane).
3. Wyłączenie optymalizacji - nic nie daje bo zmienna jest po prostu nieużywana, więc jest usunięta.
Jakieś wskazówki...?
Wydaje mi się, że dorzucanie jakiegoś timestamp'a, GCC_VER lub podobnych do pliku wynikowego jest dość powszechne, a mimo tego nie mogę znaleźć jakiegoś uniwersalnego rozwiązania (tak jak w IARze).
robię właśnie przesiadkę projektu z kompilatora IAR'a do GCC'a i mam problem z przeniesieniem niektórych ustawień, konkretniej chodzi o nie wycinanie przez linker konkretnych, nieużywanych zmiennych globalnych wygenerowanych przez zewnętrzne narzędzie, zawierających informacje np. o dacie buildu, checksumie itp. które są potem w przypadku reklamacji odczytywane po uarcie przez podanie adresu pamięci flash (zatem zmienne w kodzie nie są wprost używane).
W IARze wystarczyło dodać do zmiennej parametr "ROOT" i zmienne były dołączane do pliku wynikowego (hex), tutaj napotkałem na problem.
W najprostszej postaci wziąłem przykładowy projekt w TrueStudio (domyślnie używam gcc'a w wersji 5/2016 + eclipse). Plik wygląda następująco:
Kod: C / C++
kompilator buduje plik z następującymi parametrami (rozdzielone enterem dla czytelności):
arm-atollic-eabi-gcc -c ..\src\main.c
-mthumb -mcpu=cortex-m0
-std=gnu11
-DUSE_STM32F0_DISCOVERY -DHSI_VALUE=8000000 -DSTM32F0XX -DUSE_STDPERIPH_DRIVER
-I../src -I../Libraries/CMSIS/Include -I../Libraries/CMSIS/Device/ST/STM32F0xx/Include -I../Libraries/STM32F0xx_StdPeriph_Driver/inc -I../Utilities/STM32F0-Discovery
-Os
-ffunction-sections -fdata-sections
-g -fstack-usage -Wall -specs=nano.specs -o src\main.o
Linker, nic odkrywczego:
arm-atollic-eabi-gcc -o
STM32F0_Discovery_ADC_DMA.elf
Libraries\STM32F0xx_StdPeriph_Driver\src\stm32f0xx_adc.o
...
src\main.o
src\startup_stm32f0xx.o src\stm32f0xx_it.o
...
-lm -mthumb -mcpu=cortex-m0
-T../stm32_flash.ld
-specs=nosys.specs -static -Wl,-cref,-u,Reset_Handler -Wl,-Map=STM32F0_Discovery_ADC_DMA.map
-Wl,--gc-sections
-Wl,--defsym=malloc_getpagesize_P=0x80
-Wl,--start-group -lc -lm -Wl,--end-group -specs=nano.specs
W tej formie kompilator nie usuwa zmiennej (zrzut objdump'a z pliku main.o):
D:\Program Files (x86)\Nowy folder\TrueSTUDIO for STM32 9.0.1\ARMTools\bin>arm-atollic-eabi-objdump.exe -x -S D:\Atollic\TrueSTUDIO\STM32_workspace_9.0\STM32F0_Discovery_ADC_DMA\Debug\src\m
D:\Atollic\TrueSTUDIO\STM32_workspace_9.0\STM32F0_Discovery_ADC_DMA\Debug\src\main.o: file format elf32-littlearm
D:\Atollic\TrueSTUDIO\STM32_workspace_9.0\STM32F0_Discovery_ADC_DMA\Debug\src\main.o
architecture: arm, flags 0x00000011:
HAS_RELOC, HAS_SYMS
start address 0x00000000
private flags = 5000000: [Version5 EABI]
Sections:
Idx Name Size VMA LMA File off Algn
0 .text 00000000 00000000 00000000 00000034 2**1
CONTENTS, ALLOC, LOAD, READONLY, CODE
1 .data 00000000 00000000 00000000 00000034 2**0
CONTENTS, ALLOC, LOAD, DATA
2 .bss 00000000 00000000 00000000 00000034 2**0
ALLOC
3 .text.startup.main 00000002 00000000 00000000 00000034 2**1
CONTENTS, ALLOC, LOAD, READONLY, CODE
4 .rodata.build_info 00000005 00000000 00000000 00000036 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
5 .debug_info 000000ea 00000000 00000000 0000003b 2**0
CONTENTS, RELOC, READONLY, DEBUGGING
6 .debug_abbrev 0000008a 00000000 00000000 00000125 2**0
CONTENTS, READONLY, DEBUGGING
7 .debug_aranges 00000020 00000000 00000000 000001af 2**0
CONTENTS, RELOC, READONLY, DEBUGGING
8 .debug_ranges 00000010 00000000 00000000 000001cf 2**0
CONTENTS, RELOC, READONLY, DEBUGGING
9 .debug_line 0000016d 00000000 00000000 000001df 2**0
CONTENTS, RELOC, READONLY, DEBUGGING
10 .debug_str 000001d0 00000000 00000000 0000034c 2**0
CONTENTS, READONLY, DEBUGGING
11 .comment 0000007d 00000000 00000000 0000051c 2**0
CONTENTS, READONLY
12 .debug_frame 00000020 00000000 00000000 0000059c 2**2
CONTENTS, RELOC, READONLY, DEBUGGING
13 .ARM.attributes 00000031 00000000 00000000 000005bc 2**0
CONTENTS, READONLY
SYMBOL TABLE:
00000000 l df *ABS* 00000000 main.c
00000000 l d .text 00000000 .text
00000000 l d .data 00000000 .data
00000000 l d .bss 00000000 .bss
00000000 l d .text.startup.main 00000000 .text.startup.main
00000000 l d .rodata.build_info 00000000 .rodata.build_info
00000000 l O .rodata.build_info 00000005 build_info
00000000 l d .debug_info 00000000 .debug_info
00000000 l d .debug_abbrev 00000000 .debug_abbrev
00000000 l d .debug_aranges 00000000 .debug_aranges
00000000 l d .debug_ranges 00000000 .debug_ranges
00000000 l d .debug_line 00000000 .debug_line
00000000 l d .debug_str 00000000 .debug_str
00000000 l d .debug_frame 00000000 .debug_frame
00000000 l d .comment 00000000 .comment
00000000 l d .ARM.attributes 00000000 .ARM.attributes
00000000 g F .text.startup.main 00000002 main
Disassembly of section .text.startup.main:
00000000 <main>:
#include "stm32f0xx.h"
static const uint8_t build_info[5] __attribute__((used)) = {1,2,3,4,5};
int main(void)
{
0: e7fe b.n 0 <main>
D:\Program Files (x86)\Nowy folder\TrueSTUDIO for STM32 9.0.1\ARMTools\bin>
Po usunięciu __attribute__((used)) lub static, zmienna znika z pliku obiektu, co jest prawidłowe i zgodne z dokumentacją GCC'a .
Problem w tym, że pomimo nie usunięcia zmiennej w pliku obiektu przez kompilator, jest ona usuwana przez linker (prawdopodobnie z powodu opcji "-Wl,--gc-sections") i jest widoczna w sekcji "Discarded input sections" w pliku mapy:
Discarded input sections
...
.text 0x00000000 0x0 src\main.o
.data 0x00000000 0x0 src\main.o
.bss 0x00000000 0x0 src\main.o
.rodata.build_info
0x00000000 0x5 src\main.o
...
Oczywiście można by dodać odczyt zmiennych do jakiejś bezużytecznej zmiennej albo wstawić chociażby "asm("" :: "m" (build_info)", ale tych zmiennych jest sporo i wolałbym uniknąć dodawania kolejnego skryptu, który wygeneruje mi funkcje "odczytującą" wszystkie zmienne, to zresztą mogłoby zabierać trochę cennego miejsca we flashu.
Próbowałem już:
1. Umieścić zmienne w konkretnej sekcji, czyli dodanie sekcji w skrypcie linkera, do tego wewnątrz umieścić ją wewnątrz KEEP, czyli np. KEEP(*(.my_section)) + __attribute__((section(".my_section"))). Jeśli zmienna jest użyta, jest prawidłowo dodawana do sekcji na zadanym adresie.
2. Kombinowanie z opcjami "-ffunction-sections -fdata-sections " dla kompilatora i "-Wl,--gc-sections ", ale ich wyłączenie daje tylko nakładanie się sekcji (nic nie jest usuwane).
3. Wyłączenie optymalizacji - nic nie daje bo zmienna jest po prostu nieużywana, więc jest usunięta.
Jakieś wskazówki...?
Wydaje mi się, że dorzucanie jakiegoś timestamp'a, GCC_VER lub podobnych do pliku wynikowego jest dość powszechne, a mimo tego nie mogę znaleźć jakiegoś uniwersalnego rozwiązania (tak jak w IARze).