2012-02-15 16 views
7

Gcc tabanlı bir çıplak metal mcu projesi oluştururken, başlatma sırasında .data ve .bss bölümlerinin başlatılmasına dikkat etmeniz gerekir..data bölümünün init verilerini nereden alması gerektiğini nereden öğrenebilirim? (gcc linker)

Tüm bölümü yalnızca 0 olarak doldurduğumdan, .bss bölümü oldukça kolaydır. Ancak, .data bölümündeki değişkenlerin, başlatma/başlatma/oynatma sırasında rom/flash biçiminde olması ve başlangıç ​​sırasında kopyalanması gerekir.

Başlatma değerleri ile verilerin nerede bulunduğunu nasıl bilebilirim?

Bir örnek verelim.

ı

unsigned int my_global_variable_one = 1; 
unsigned int my_global_variable_two = 2; 

Sonra onlar, ne olacağını bölümünde görmek için nesne dosyası üzerinde objdump kullanabilirsiniz main.c iki küresel değişkenler oluşturmak diyelim ama bir şey bulamıyorum init verisinin yerleştirilmesi gereken objdump dışarı.

$ arm-none-eabi-objdump --syms main.o | grep my_global_variable 
00000000 g  O .data 00000004 my_global_variable_one 
00000004 g  O .data 00000004 my_global_variable_two 

Ardından, tüm sistem için elde edilen elf'e, bu durumda ana bilgisayara bakabilirim.

$ arm-none-eabi-nm -n main.elf | grep my_global_variable 
20000000 D my_global_variable_one 
20000004 D my_global_variable_two 

Bulundukları yeri nereden bulabilirim, böylece verileri kopyalayabilirim? Linker betiğimde nelere ihtiyacım var?

.text veya .rodata gibi bir şeyde olmalı, ancak nasıl öğrenebilirim?

my_global_variable_one için init verilerinin nerede olduğunu nasıl kontrol edebilirim?

Bu verilerin, readelf veya objdump gibi binutils komutlarından herhangi biriyle nerede olduğunu bulabilir miyim?

/sayesinde

Bu STM32 üzerinde

(Cortex M3) MCU ve gcc CodeBench versiyonu kullanılmıştır.

cevap

9

Derleyici, .text bölümündeki tüm kod ve salt okunur bazı verileri koyar. Ayrıca .rodata bölümü de olabilir. Eğer bağlayıcı komut böyle bir ROM adres şey koymak olabilir:

derleyici .data bölümünde yazılabilir verilerin tümünü ilk değerlerini koyar
. = <rom-base-address>; 
.rodata : { *(.rodata) } 
<other read-only sections go here> 
.text : { *(.text) } 

ve tüm semboller bir başlangıç ​​değeri de yok .bss. .bss kolaydır, bunu sadece RAM'e yerleştirirsiniz. .data çalışma zamanında RAM içinde olmak istiyor, ancak yük anda ROM ve bağlayıcı komut size AT anahtar kelime ile bunu sağlar:

. = <ram-base-address>; 
.bss : { *(.bss) } 
.data : AT (ADDR (.text) + SIZEOF (.text)) 
     { *(.data) } 

Bu veri bölümü artık farklı bir LMA sahip olduğu anlamına gelir ve VMA (Bellek Adresi/Sanal Bellek Adresi Yükle). Programınız VMA'daki verileri (çalışma zamanı adresi) bulmayı bekleyecektir, ancak veriler aslında LMA'da mevcut olacaktır (flaşörünüzün bunu yapmasını öğretmeniz gerekebilir), bu da .text bölümünün hemen sonrasındadır.

Buradan nereye kopyalanacağını bulmanız gerekiyorsa, bağlayıcı komut dosyasında işaretçiler oluşturabilirsiniz. Yani, böyle yukarıdaki örneği değiştirin:

.data : AT (ADDR (.text) + SIZEOF (.text)) 
     { _data_lma = LOADADDR(.data); _data_vma = .; 
      *(.data); 
      _data_size = SIZEOF (.data);} 

Ardından başlangıç ​​kodunda memcpy (_data_vma, _data_lma, _data_size) yapabilirsiniz olanlar semboller program olarak sabit görünür (? Eğer el kod assembler bulunabilecek rağmen) bağlantı zamanında çözülen globals.

_data_lma_k: 
    .long _data_lma 

Ardından numara sert .text bölüme kodlu olacak: Yani, sizin montajcı kodu gibi bir şey olabilir. Tabii ki, assembler sözdizimi platformunuzda farklı olabilir.

fazla bilgi için

, manuel bağlayıcı bakınız here

+0

Eh veri .text bölümden sonra eklenir fark ama beni yeterince yakın olsun yardımcı oldu :) – Johan