zapis wartosci zmiennych w odniesieniu do rodzaju pamięci

0

Witam.

Załóżmy że nasz mikrokontroler np.8 bitowy AVR ma pamięć Flash i RAM.
W programie tworzymy dwa rodzaje zmiennych globalnych:

uint8_t x = 5;
const uint8_t y = 10;

Pytanie brzmi: w jakich rodzajach pamięci (flash czy RAM) zostaną umieszczone owe zmienne ?
Które z tych zmiennych zostaną przekopiowane z Flasha do RAM'u i kiedy to nastąpi (na początku czy dopiero gdy zechcemy danej zmiennej użyć) ?

Czy zależy to od architektury procesora (harvardzka lub von neumanna) ?

Z góry dzięki za odpowiedzi.

0

Zależy od skryptu linkera i lokalizacji sekcji .data i .rodata.
Kopiowanie zwykle (mówię na podstawie doświadczenia z ARM Cortex M3) następuje w trakcie wczesnego rozruchu urządzenia, gdzieś na początku handlera resetu.

0

Zmienną zostaną utworzone w pamięci ram. Nie da się w prosty sposób zapisywać do flasha (chociaż jest taka możliwość, tak samo do eeprom).
Zmienne globalne zostaną załadowane na początku funkcji main w sekcji init.

0

Konsultowałem to z kolegą z pracy. Twierdzi, że jeśli zmienna jest jednocześnie definiowana i inicjalizowana np.. instrukcją:

const uint8_t x = 5;

To wówczas będzie tworzona we flashu. Później jak trafimy na instrukcję przepisania :

uint8_t y = x;

to procek ładuje tą stałą z pamięci flash do rejestru a następnie z rejestru do RAMu pod adres przydzielony pod zmienną y.
To przeczy temu co pisze kolega w ostatnim poście.
Na dowód tego przytaczam również podstawową wiedzę dot. przechowywania "stringów". Wyczytałem że aby nie zajmować zbyt dużo RAMu powinno się tworzyć stringi jako const bo wówczas właśnie będą umieszczone we flashu a nie w RAMie. W ramie będzie umieszczony jedynie wskaźnik w trakcie gdy potrzebujemy pobrać "zawartość tego stringa":

const char str[] = "Ala ma kota.";

Generalnie to pisze kolega że "nie da się w prosty sposób zapisywać do flasha" - a ja chciałbym się do tego odnieść w taki sposób że my przecież nie chcemy nic "zapisywać" do flasha w trakcie działania programu ponieważ jest to niemodyfikowalna stała.
Będzie raczej tak że podczas kompilacji wygenerowana zostaje binarka którą programujemy ten flash a która to zawiera już "zahardcodowaną" wartość tej stałej.

Chciałbym się generalnie dowiedzieć czy zawsze stałe definiowane oczywiście z const zostaną umieszczone we flashu, ewentualnie kiedy nie tam, tylko w ramie. No bo rzeczywiście co się stanie w przypadku gdy będzie tak :

const uint8_t x;

void fun1()
{
    x = 5;
}

void fun2()
{
    x = 10;
}

że w czasie działania programu może wystąpić wywołanie jednorazowo tylko jednej z tych dwóch funkcji ale od tego której to wynika bezpośrednio z działania programu i jest nieprzewidywalne. Wówczas może być tak że stała x będzie umieszczona w ramie na skutek tego że jak pisze kolega "nie da się w prosty sposób zapisywać do flasha".

Zresztą co kolega ma na myśli pisząc że "nie da się w prosty sposób zapisywać do flasha" ? Czy mógłby kolega rozwinąć tą sentencję ?

Oraz czy taki kod z dwoma funkcjami inicjalizującymi stałą różną od siebie wartością się skompiluje czy nie ?

0

Czytałem w pośpiechu.
Co do flash'a , chodzi mi o dynamiczne zapisywanie. Normalnie nie da się tego zrobić ale jest sposób flash self. Tak jak eeprom.
Nie zmienia to komórki która jest aktualnie wczytana.

Zobacz jak u Ciebie wygląda - avr-objdump -D plik_przed_hex.
W zależności od optymalizacji kod będzie wyglądał całkowicie inaczej i inaczej będzie inicjalizowany.
W dużym uproszczeniu:

  1. jak zależy Ci na małej zajętości w ramie, większej prędkości to -O3/-O1 (-O2 produkuje to samo dla avr-gcc co -O3)
  2. jak zależy Ci na flashu to -Os

Oba kody i sposoby inicjalizacji będą wyglądały całkowicie inaczej. Pisałem dla przykładu -Os, bo wydaje mi się bardziej sensowny.

0

Adamos19: Tak naprawdę, to patrzysz na to bardzo wysokopoziomowo. W przypadku mikrokontrolerów wszystkie zainicjalizowane zmienne muszą wylądować we flashu tak czy siak, bo po resecie w RAM-ie mogą być albo śmieci albo zera. Skrypt linkera odpowiada za to, żeby wygenerować obraz do flasha, a wczesny bootstrap w asemblerze jedną pętlą przerzuca całą sekcję data do RAMu na podstawie symboli podefiniowanych w skrypcie linkera i oznaczających np. początek i rozmiar sekcji.

1 użytkowników online, w tym zalogowanych: 0, gości: 1