Bir mikrodenetleyicinin farklı bellek tiplerinde neler bulunur?


25

Derleme işleminden sonra çeşitli veri türlerinin C kodundan eklendiği farklı bellek bölümleri vardır. Yani: .text, .data, .bss, konsol ve yığın. Sadece bu bölümlerin her birinin bir mikrodenetleyici hafızasında nerede bulunacağını bilmek istiyorum. Yani, hangi tip hafızaya girilirse, hafıza tipleri RAM, NVRAM, ROM, EEPROM, FLASH vs.

Burada benzer soruların cevaplarını buldum, ancak farklı bellek türlerinin her birinin içeriğinin ne olacağını açıklayamadılar.

Her türlü yardım son derece takdir edilmektedir. Şimdiden teşekkürler!


1
NVRAM, ROM, EEPROM ve Flash, aynı şey için hemen hemen sadece farklı isimlerdir: uçucu olmayan bellek.
Lundin

Soruya biraz teğet olur, fakat kod (istisnai olarak), özellikle yama veya kalibrasyon kullanımlarını düşünürseniz, bunlardan birçoğunda güzelce bulunabilir. Bazen yürütmeden önce taşınır, bazen de yürütülür.
Sean Houlihane

@SeanHoulihane OP, hemen hemen her zaman Flash dışında çalışan mikro denetleyiciler hakkında sorular soruyor (yorumunuzu istisnai olarak nitelendirdiniz). Mesela Linux çalıştıran MB'lık harici RAM'lı mikro işlemciler , belki de monte edilebilir bir birim olarak işlev gören bir SD kartın dışında programlarını RAM'e kopyalarlar.
tcrosley

@tcrosley Artık TCM'li mikrodenetleyiciler var ve bazen mikrodenetleyiciler daha büyük bir SoC'nin parçası. Ayrıca, mcu'ların kendisini RAM'den kendi depolarından çıkarmaya zorladıkları eMMC cihazları gibi durumlar olduğundan da şüpheliyim (birkaç yıl öncesine dayanan bazı telefonların hafızalarına dayanarak). Kabul ediyorum, doğrudan bir cevap değil - ama tipik haritalamaların hiçbir şekilde zor kurallar olmadığı konusunda çok anlamlı olduğunu düşünüyorum.
Sean Houlihane

1
Bir şeyi diğerine bağlamak için hiçbir kural yoktur, sadece text ve rodata gibi salt okunur şeyler yanıp sönmek isterdi, ancak .data ve .bss ofset ve boyutu da oraya gider (ve sonra kopyalanır. önyükleme kodu). Bu terimlerin (.text, vb.) mikrodenetleyicilerle ilgisi yoktur, derleyici / araç zincirlerinin tüm hedefleri için geçerli olan bir derleyici / araç zinciridir. günün sonunda, programcı işlerin nereye gittiğine karar verir ve genellikle bir linker betiği aracılığıyla takım zincirini bilgilendirir.
old_timer

Yanıtlar:


38

.Metin

.Text segmenti gerçek kodu içerir ve mikrodenetleyiciler için Flash belleğe programlanır. Birden çok bitişik olmayan Flash bellek bloğu olduğunda birden fazla metin segmenti olabilir; örneğin, hafızanın en üstünde bulunan bir başlangıç ​​vektörü ve kesme vektörleri ve 0'dan başlayan kod; veya bir önyükleme ve ana program için ayrı bölümler.

.bss ve .data

Bir işleve veya prosedüre harici olarak tahsis edilebilecek üç tür veri vardır; birincisi başlatılmamış veridir (başlangıçta 0 başlatılmış veriyi de içeren tarihsel olarak .bss olarak adlandırılır) ve ikincisi başlatılmıştır (bss dışı) veya .data. "Bss" ismi, tarihsel olarak, yaklaşık 60 yıl önce bir montajcıda kullanılan "Symbol tarafından Başlatılan Blok" kelimesinden gelir. Bu alanların her ikisi de RAM'de bulunur.

Bir program derlenirken değişkenler bu iki genel alandan birine tahsis edilecektir. Bağlantı aşamasında, tüm veri maddeleri bir araya toplanacaktır. Başlatılması gereken tüm değişkenler, başlangıç ​​değerlerini tutmak için ayrılan program belleğinin bir bölümünü tutacaktır ve main () çağrılmadan hemen önce, değişkenler tipik olarak crt0 adlı bir modül tarafından başlatılacaktır. Bss bölümü aynı sıfır kodu ile tüm sıfırlara sıfırlanır.

Birkaç mikrodenetleyiciyle, RAM'in ilk sayfasına (ilk 256 konum, bazen sayfa 0 olarak adlandırılır) erişime izin veren daha kısa talimatlar vardır. Bu işlemciler için derleyici near, oraya yerleştirilecek değişkenleri belirtmek gibi bir anahtar kelime saklayabilir. Benzer şekilde, yalnızca belirli alanlara bir işaretçi yazıcısı aracılığıyla başvurabilen (ek talimatlar gerektiren) mikrodenetleyiciler de vardır ve bu değişkenler belirlenir far. Son olarak, bazı işlemciler bit bellek belleğinin bir bölümünü ele alabilir ve derleyicinin bunu (anahtar kelime gibi) belirtmek için bir yolu olur bit.

Dolayısıyla, bu değişkenlerin toplandığı .nearbss ve .neardata vb. Gibi ek parçalar olabilir.

.rodata

Bir işlev veya yordamın dışındaki üçüncü veri türü, salt okunur olması ve program tarafından değiştirilememesi dışında, başlatılan değişkenlere benzer. C dilinde, bu değişkenler constanahtar kelime kullanılarak belirtilir . Genellikle programın flash belleğinin bir parçası olarak kaydedilirler. Bazen bir .rodata (salt okunur veri) bölümünün bir parçası olarak tanımlanırlar. Harvard mimarisini kullanan mikrodenetleyicilerde , derleyici bu değişkenlere erişmek için özel talimatlar kullanmalıdır.

yığın ve yığın

Yığın ve yığının her ikisi de RAM'e yerleştirilir. İşlemcinin mimarisine bağlı olarak, yığın büyüyebilir veya küçülebilir. Büyürse, RAM'in altına yerleştirilir. Büyürse, RAM'in sonuna yerleştirilir. Öbek, değişkenlere tahsis edilmemiş kalan RAM'i kullanır ve yığının ters yönünü büyütür. Yığın ve yığının maksimum boyutu genellikle bağlayıcı parametreleri olarak belirtilebilir.

Yığına yerleştirilen değişkenler, bir işlev veya yordam içinde anahtar sözcük olmadan tanımlanan değişkenlerdir static. Bir zamanlar otomatik değişkenler ( autoanahtar kelime) olarak adlandırılıyorlardı , ancak bu anahtar kelimeye gerek yok. Tarihsel olarak, autoC'den önce gelen B dilin bir parçası olduğu için var olur ve orada buna ihtiyaç vardı. İşlev parametreleri de yığına yerleştirilir.

RAM için tipik bir sayfa düzeni (özel sayfa 0 bölüm olmadığını varsayarak):

görüntü tanımını buraya girin

EEPROM, ROM ve NVRAM

Flash bellek gelmeden önce, programı depolamak ve verileri (.text ve .rodata segmentleri) depolamak için EEPROM (elektrikle silinebilir programlanabilir salt okunur bellek) kullanıldı. Şimdi, eğer varsa, sadece küçük bir miktar (örn. 2KB - 8KB bayt) EEPROM mevcuttur ve tipik olarak, çalıştırma sırasında açılmalarında tutulması gereken yapılandırma verilerini veya diğer küçük miktarda verileri depolamak için kullanılır. Çevrim. Bunlar programda değişkenler olarak bildirilmez, bunun yerine mikrodenetleyicide özel kayıtları kullanmak için yazılır. EEPROM ayrıca ayrı bir yongada da uygulanabilir ve bir SPI veya I²C veriyolu üzerinden erişilebilir.

ROM, fabrikada programlanması haricinde, Flash ile aynıdır (kullanıcı tarafından programlanamaz). Sadece çok yüksek hacimli cihazlar için kullanılır.

NVRAM (uçucu olmayan RAM), EEPROM'a bir alternatiftir ve genellikle harici bir IC olarak uygulanır. Batarya destekliyse, düzenli RAM kalıcı değildir; Bu durumda özel erişim yöntemlerine gerek yoktur.

Veriler Flash'a kaydedilebilse de, Flash belleğin sınırlı sayıda silme / program döngüsü vardır (1000 ila 10.000), bu nedenle bunun için tasarlanmamıştır. Aynı zamanda bir kerede silinmesi gereken bellek bloklarını gerektirir, bu yüzden sadece birkaç byte güncellemek sakıncalıdır. Kod ve salt okunur değişkenler için tasarlanmıştır.

EEPROM'un silme / program döngüleri (100.000 - 1.000.000) arasında çok daha yüksek sınırları vardır, bu nedenle bu amaç için çok daha iyidir. Mikrodenetleyicide EEPROM varsa ve yeterince büyükse, kalıcı olmayan verileri kaydetmek istediğiniz yerdir. Ancak, yazmadan önce ilk önce (genellikle 4KB) blokları silmeniz gerekir.

EEPROM yoksa veya çok küçükse, harici bir yonga gerekir. 32KB EEPROM sadece 66 ¢'dır ve 1.000.000 defa silinebilir / yazılabilir. Aynı sayıda silme / program işlemine sahip bir NVRAM çok daha pahalıdır (x10) NVRAM'lar genellikle okuma için EEPROM'lardan daha hızlıdır, ancak yazma için daha yavaştır. Bir seferde bir byte'a veya bloklar halinde yazılabilirler.

Bunların her ikisine de daha iyi bir alternatif, temel olarak sınırsız yazma döngüleri (100 trilyon) olan ve yazma gecikmeleri olmayan FRAM'dir (ferroelektrik RAM). NVRAM ile aynı fiyatta, 32KB için 5 dolar civarında.


Bu gerçekten faydalı bir bilgi parçasıydı. Lütfen açıklamanız için bir referans verebilir misiniz? Ders kitapları veya dergiler gibi, bu konuda daha fazla şey okumak istersem ..?
Soju T Varghese

bir soru daha, lütfen bir belleğin diğerine göre avantajları veya dezavantajları hakkında bir fikir verebilir misiniz (EEPROM, NVRAM ve FLASH)?
Soju T Varghese

Güzel cevap Özellikle C dilinde neyin nereye gittiğine daha fazla odaklanan tamamlayıcı bir tane yayınladım.
Lundin

1
@SojuTVarghese Cevabımı güncelledim ve FRAM ile ilgili bazı bilgiler de ekledim.
tcrosley

@Lundin'de aynı segment adlarını (ör.
tcrosley

21

Normal gömülü sistem:

Segment     Memory   Contents

.data       RAM      Explicitly initialized variables with static storage duration
.bss        RAM      Zero-initialized variables with static storage duration
.stack      RAM      Local variables and function call parameters
.heap       RAM      Dynamically allocated variables (usually not used in embedded systems)
.rodata     ROM      const variables with static storage duration. String literals.
.text       ROM      The program. Integer constants. Initializer lists.

Ek olarak, başlangıç ​​kodu ve kesme vektörleri için genellikle ayrı flaş bölümleri vardır.


Açıklama:

Bir değişkenin, staticdosya kapsamı içinde yer alması veya belirtilmesi durumunda (bazen "genel" olarak da adlandırılır) statik depolama süresi vardır . C, programcının açıkça başlatmadığı tüm statik depolama süresi değişkenlerinin sıfıra başlatılması gerektiğini belirten bir kurala sahiptir.

Sıfıra, dolaylı veya açık bir şekilde başlatılan her statik depolama süresi değişkeni sona erer .bss. Açıkça sıfır olmayan bir değere ilklendirilenler ise bitiyor .data.

Örnekler:

static int a;                // .bss
static int b = 0;            // .bss      
int c;                       // .bss
static int d = 1;            // .data
int e = 1;                   // .data

void func (void)
{
  static int x;              // .bss
  static int y = 0;          // .bss
  static int z = 1;          // .data
  static int* ptr = NULL;    // .bss
}

Gömülü sistemler için çok yaygın bir standart dışı kurulum "minimal başlangıç-up", sahip olduğu unutmayın hangi programın atlar demekse tüm statik depolama süresi olan nesnelerin başlatılmasını . Bu nedenle, asla bu tür değişkenlerin başlangıç ​​değerlerine dayanan programlar yazmamanız, bunun yerine bunları ilk kez kullanılmadan önce "çalışma zamanında" ayarlamasının akıllıca olabilir.

Diğer segmentlere örnekler:

const int a = 0;           // .rodata
const int b;               // .rodata (nonsense code but C allows it, unlike C++)
static const int c = 0;    // .rodata
static const int d = 1;    // .rodata

void func (int param)      // .stack
{
  int e;                   // .stack
  int f=0;                 // .stack
  int g=1;                 // .stack
  const int h=param;       // .stack
  static const int i=1;    // .rodata, static storage duration

  char* ptr;               // ptr goes to .stack
  ptr = malloc(1);         // pointed-at memory goes to .heap
}

Yığında gidebilen değişkenler, optimizasyon sırasında sıklıkla CPU kayıtlarına neden olabilir. Genel bir kural olarak, adresi alınmamış herhangi bir değişken bir CPU kaydına yerleştirilebilir.

constİşaretçilerin , diğer değişkenlerden biraz daha karmaşık olduklarını unutmayın; çünkü , belirtilen verilerin salt okunur olması gerektiğine veya işaretçinin kendisinin olması gerektiğine bağlı olarak iki farklı türde izin verir . Aradaki farkı bilmek çok önemlidir, bu nedenle işaretçilerinizin RAM'le çakılmalarını istemeyin.

int* j=0;                  // .bss
const int* k=0;            // .bss, non-const pointer to const data
int* const l=0;            // .rodata, const pointer to non-const data
const int* const m=0;      // .rodata, const pointer to const data

void (*fptr1)(void);       // .bss
void (*const fptr2)(void); // .rodata
void (const* fptr3)(void); // invalid, doesn't make sense since functions can't be modified

Tamsayı sabitleri durumunda, başlatıcı listeleri, string değişmezleri vb. Derleyiciye bağlı olarak .text veya .rodata olabilir. Muhtemelen, sonunda:

#define n 0                // .text
int o = 5;                 // 5 goes to .text (part of the instruction)
int p[] = {1,2,3};         // {1,2,3} goes to .text
char q[] = "hello";        // "hello" goes to .rodata

Anlamıyorum, ilk örnek kodunuzda, neden 'static int b = 0;' .bss'ye gider ve neden 'statik int d = 1;' .dataya giriyor ..? Anladığım kadarıyla, her ikisi de programcı tarafından başlatılan statik değişkenler. @Lundin
Soju T Varghese

2
@SojuTVarghese Çünkü .bss verileri 0 olarak bir blok olarak başlatıldı; d = 1 gibi belirli değerlerin flaşta saklanması gerekir.
tcrosley

@SojuTVarghese Bazı açıklamalar eklendi.
Lundin

@Lundin Ayrıca, son örnek kodunuzdan, başlatılan tüm değerlerin .text veya .rodata'ya ve ilgili değişkenlerin tek başına .bss veya .data'ya girdiği anlamına mı geliyor? Eğer öyleyse, değişkenler ve karşılık gelen değerleri birbirlerine nasıl eşlenir (yani .bss / .data ve .text / .rodata segmentleri arasında)?
Soju T Varghese

@SojuTVarghese Hayır, .datatipik olarak flaşta , başlangıç ​​değerlerinin depolandığı bir yükleme adresi ve RAM'de, değişken yürütme sırasında değişkenin depolandığı sanal bir adres (bir mikro denetleyicide gerçekten sanal değil) bulunur. Başlamadan önce mainilk değerler yükleme adresinden sanal adrese kopyalanır. Sıfırları kaydetmeniz gerekmez, bu nedenle .bssbaşlangıç ​​değerlerini kaydetmeniz gerekmez. sourceware.org/binutils/docs/ld/…
starblue

1

Herhangi bir veri programcının seçtiği herhangi bir hafızaya girebilse de, verilerin kullanım profilinin hafızanın okuma / yazma profilleriyle eşleştiği yerlerde genellikle sistem en iyi şekilde çalışır (ve kullanılması amaçlanmıştır).

Örneğin, program kodu WFRM'dir (çok azını yazın) Bu FLASH'a çok yakışmış. ROM OTOH, bir kez RM'dir.

Yığın ve yığın küçüktür, birçok okur ve yazar. RAM en iyi olurdu.

EEPROM, bu kullanımların ikisine de uygun gelmeyecek, ancak açılışta karşı karşıya kalan küçük miktarlardaki verilerin profiline, dolayısıyla kullanıcıya özel başlatma verilerine ve belki de sonuçların kaydına uygun olacaktır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.