2013-03-07 10 views
7

Ponieważ jestem stosunkowo nowy w C, muszę użyć do jednego z moich projektów: Muszę zadeklarować niektóre zmienne globalne, które muszą być przechowywane za każdym razem, gdy program działa pod tym samym adresem pamięci. Zrobiłem kilka odczytów i znalazłem, że jest to, że deklaruję "statyczne", że będzie przechowywane w tej samej lokalizacji pamięci.Jak zapisać zmienną w określonej lokalizacji pamięci?

Ale moje pytanie brzmi: czy mogę wskazać program, w którym ma być przechowywana ta zmienna lub nie. Na przykład: int a ma być przechowywany w 0xff520000. Czy można to zrobić, czy nie? szukałem tutaj, ale nie znalazłem żadnego odpowiedniego przykładu. Jeśli jest to jakiś stary post w związku z tym, uprzejmie prosimy o udostępnienie linku.

Dziękuję wszystkim z góry. Laurentiu

Aktualizacja: używam 32uC

+1

To wspólne dla systemów wbudowanych mieć rejestrów sprzętowych w określonych adresów. Jednak na normalnym komputerze nie można przewidzieć, gdzie znajdą się zmienne, i podobnie nie można umieszczać zmiennych w określonych lokalizacjach pamięci, ponieważ mapa pamięci programu nie jest naprawiona. Czy jest to system wbudowany lub zwykły komputer? –

+1

Dlaczego adres ma znaczenie? W każdym razie jest to ** wirtualna ** pamięć. – UmNyobe

+0

Witam, muszę wykonać następujące czynności. Wykonaj swoistą platformę testową dla 32-bitowego uC, ale po flashowaniu przez OCD, platforma powinna mieć (działać) na komunikacji UART. I powiedzmy, że mam licznik, który policzy, ile czasu uruchomił program, lub licznik czasu, w którym program działa bezbłędnie, potem mój profesor, co podać jako wejście przez Hyper Terminal adres, w którym znajduje się ten licznik zmiennych, w celu uzyskania jego wartości. Właśnie tego potrzebuję .. wszelkie pomysły: – Laurentiu

Odpowiedz

10

W twoim IDE będzie dostępna mapa pamięci dostępna poprzez jakiś plik linkera. Będzie zawierał wszystkie adresy w programie. Przeczytaj podręcznik MCU, aby zobaczyć, w których adresach znajduje się ważna pamięć dla twojego celu, a następnie zarezerwuj część tej pamięci dla swojej zmiennej. Musisz przeczytać dokumentację swojej konkretnej platformy programistycznej.

Następnie należy pamiętać, że nie ma większego sensu mapowanie zmiennych pod określonymi adresami, chyba że są to rejestry sprzętowe lub nielotne zmienne rezydujące w pamięci flash lub EEPROM.

Jeśli zawartość takiej lokalizacji pamięci zmieni się podczas wykonywania, ponieważ jest to rejestr, lub ponieważ twój program zawiera algorytm programujący bootloader/NVM zmieniający komórki pamięci NVM, to zmienne muszą być zadeklarowane jako zmienne. W przeciwnym razie kompilator całkowicie złamie kod po optymalizacji.

Poszczególny kompilator najprawdopodobniej ma niestandardowy sposób przydzielania zmiennych pod konkretnymi adresami, na przykład #pragma lub czasami dziwnym, niestandardowym operatorem @. Jedyny sensowny sposób można przydzielić zmiennej w stałym miejscu w standardowej C, to:

#define MY_REGISTER (*(volatile uint8_t*)0x12345678u) 

gdzie 0x12345678 jest adres gdzie 1 bajt, który jest położony. Raz masz makro deklarację takiego, można go używać tak, jakby to była zmienna:

void func (void) 
{ 
    MY_REGISTER = 1; // write 
    int var = MY_REGISTER; // read 
} 

Najczęściej chcesz tego rodzaju zmiennych do przebywania w globalnej przestrzeni nazw, stąd makro. Ale jeśli z jakiegoś powodu chcą zakres zmiennej zostać zmniejszona, a następnie przejść makro i dostępu do adresu ręcznie wewnątrz kodu:

void func (void) 
{ 
    *(volatile uint8_t*)0x12345678u = 1; // write 
    int var = *(volatile uint8_t*)0x12345678u; // read 
} 
+0

Dziękuję.Tego właśnie chciałem. Wziąłem swoje rady i znaleźć następujące: pamięć IROM \t: POCHODZENIE = 0x00000000, \t długość = 3072k Iram \t: POCHODZENIE = 0xFEDC0000, \t długość = 256k BURAM \t: POCHODZENIE = 0xFF760000, \t długość = 16k
Przypuszczam musicie wybrać jakiś zakres od RAMu z tego, czego potrzebuję, prawda? – Laurentiu

+1

Przy okazji: dlaczego użyłem adresu takiego jak 0x12345678u? co reprezentujesz z końca? – Laurentiu

+2

@Laurentiu Sufiks 'u' (lub' U') oznacza, że ​​liczba całkowita jest typu "unsigned". Jest tam, aby zagwarantować, że zostanie użyty typ wcięty, napisałem go głównie ze starego zwyczaju. Dosłownie w źródle C jest domyślnie typu (podpis) 'int', ale ponieważ adres nie może nigdy być ujemny, nie ma sensu używać zapisanej zmiennej do jego przechowywania. Ogólnie rzecz biorąc, nigdy nie chcesz używać domyślnego typu 'int' w systemach wbudowanych. W niektórych przypadkach, gdy wykonujesz zwykłą arytmetykę, możesz chcieć użyć typów 'sintN_t', gdzie N = 8, 16 itd. Ale przez większość czasu używasz tylko niepodpisanych zmiennych. – Lundin

1

No nie można powiedzieć to wyraźnie gdzie przechowywać zmiennej w pamięci. Głównie dlatego, że w nowoczesnych systemach masz wiele rzeczy zrobionych przez system w odniesieniu do pamięci, która jest poza twoją kontrolą. Układ adresów Randomizacja to jedna rzecz, która przychodzi na myśl, co bardzo utrudniałoby to.

0

Nie na poziomie C. Jeśli pracujesz z językiem asemblerowym, możesz bezpośrednio sterować układem pamięci. Ale kompilator C robi to za Ciebie. Naprawdę nie możesz z tym pogodzić.

Nawet przy montażu kontroluje tylko układ względny. Pamięć wirtualna może umieszczać to w dowolnej (nie) dogodnej fizycznej lokalizacji.

8

Możesz to zrobić za pomocą skryptów linkerów, co jest dość powszechne w programowaniu wbudowanym.

W systemie Linux nigdy nie można uzyskać tego samego adresu wirtualnego z powodu randomizacji przestrzeni adresowej (funkcja bezpieczeństwa w celu uniknięcia exploitów, które polegałyby na znajomości dokładnej lokalizacji takiej zmiennej jak opisywana).

Jeśli potrzebujesz tylko powtarzalnego wskaźnika, być może będziesz mógł zamapować określony adres na mmap, ale nie jest to gwarantowane.

+0

Prawda. Jak myślę, używanie mmap do mapowania przestrzeni adresowej do pliku mogłoby rozwiązać problem. Trzeba tylko dbać o to, aby mmap (CONST_ADDR, ....., fd, CONST_FILE_OFFSET); nigdy nie zawiedzie (lub mapuje na diff-addr niż COSNT_ADDR). Wtedy CONST_ADDR staje się adresem zmiennej globalnej, a zmiany dokonane w tym globalnym liczniku będą odzwierciedlone w pliku, który może być użyty dalej w następnym programie. –

0

Możesz to zrobić z niektórymi rozszerzeniami kompilatora, ale prawdopodobnie nie jest to, co chcesz zrobić. System operacyjny obsługuje twoją pamięć i umieszcza rzeczy tam, gdzie chce. Skąd wiesz, że żądany adres pamięci zostanie zmapowany w twoim programie? Zignoruj ​​wszystko w tym paragrafie, jeśli jesteś na platformie wbudowanej, powinieneś przeczytać instrukcję tej platformy/kompilatora lub przynajmniej wspomnieć o tym tutaj, aby ludzie mogli podać bardziej konkretną odpowiedź.

Ponadto zmienne statyczne nie muszą mieć tego samego adresu podczas działania programu. Wiele systemów operacyjnych używa plików niezależnych od pozycji i wybiera losowo przestrzeń adresową przy każdym wykonaniu.

0

Można zadeklarować wskaźnik do określonego adresu pamięci i używać zawartość tego wskaźnika jako zmienna przypuszczam:

int* myIntPointer = 0xff520000; 
+0

typecast it .... – anishsane

1

Jak wspomniano w innych odpowiedzi - nie można. Ale można obejść. Jeśli to jest ok za globalne być inicjowane w main(), można zrobić coś z tego rodzaju:

int addr = 0xff520000; 

int main() 
{ 
    *((int*)addr) = 42; 
    ... 
    return 0; 
} 

jednak pamiętać, że jest to bardzo zależy od systemu i jeśli działa w chronionym środowisku, będziesz najprawdopodobniej nastąpi awaria runtime.Jeśli jesteś w środowisku osadzonym/niechronionym, to może działać.

+0

Ten działa. Ale czy możesz mi powiedzieć, w jaki sposób mogę znaleźć miejsce, w którym mogę przechowywać moją zmienną? Bo przypuszczam, że nie mogę używać niektórych obszarów pamięci ramek w uC? – Laurentiu

+0

@Laurentiu W twoim IDE będzie dostępna mapa pamięci dostępna poprzez jakiś plik linkera. Będzie zawierał wszystkie adresy w programie. Przeczytaj podręcznik MCU, aby zobaczyć, w których adresach znajduje się ważna pamięć dla twojego celu, a następnie zarezerwuj część tej pamięci dla swojej zmiennej. Musisz przeczytać dokumentację swojej konkretnej platformy programistycznej. – Lundin

Powiązane problemy