CVAVR - jak nie inicjalizować wartości zm

Jan 27, 2009 19 Replies

Witam Nie jestem biegły w programowaniu i mam taki problem odnośnie AVRka programowanego za pomocą CodeVision AVR.



Otóż potrzebuję na początku programu sprawdzić wartość 2 komórek pamięci RAM. Zakładam, że komórki te mają wartość taka jak poprzednio, jeśli napięcie zasilania nie spadło poniżej pewnego poziomu. Podobnie robię w PICach i to się dobrze sprawdza.


Umiem zmusić program do umieszczenia danych w konkretnym obszarze, robi się dodając adres po nazwie zmiennej, np. char data @0x60; jednak z tego co widzę, to nawet pomimo wyłączonej opcji: clear global variables at program startup w konfiguracji projektu - wygląda na to, że te zmienne są zerowane.


To co mi przychodzi na myśl, to użyć jakiejś wstawki assemblerowej, gdzie będę kopiował wartość z komórki RAM o konkretnym adresie do jakiejś zmiennej w C. Potrzebuję tak przekopiować dwie komórki, które mają nie być zerowane przy inicjalizacji.



Proszę o pomoc


...zainstaluj AVR Studio4, CV generuje plik COF dzieki temu przejrzysz dokłądnie asemblera krok po kroku... Pzdr.

;GLOBAL VARIABLES INITIALIZATION LDI R30,LOW(__GLOBAL_INI_TBL*2) LDI R31,HIGH(__GLOBAL_INI_TBL*2) __GLOBAL_INI_NEXT: LPM R24,Z+ LPM R25,Z+ SBIW R24,0 BREQ __GLOBAL_INI_END LPM R26,Z+ LPM R27,Z+ LPM R0,Z+ LPM R1,Z+ MOVW R22,R30 MOVW R30,R0 __GLOBAL_INI_LOOP: LPM R0,Z+ ST X+,R0 SBIW R24,1 BRNE __GLOBAL_INI_LOOP MOVW R30,R22 RJMP __GLOBAL_INI_NEXT __GLOBAL_INI_END:

PawelM pisze:

Ogólnie z podejrzeniem ASM nie ma problemu

Występuje taka sekcja:

;GLOBAL VARIABLES INITIALIZATION LDI R30,LOW(__GLOBAL_INI_TBL*2) LDI R31,HIGH(__GLOBAL_INI_TBL*2) __GLOBAL_INI_NEXT: LPM R24,Z+ LPM R25,Z+ SBIW R24,0 BREQ __GLOBAL_INI_END LPM R26,Z+ LPM R27,Z+ LPM R0,Z+ LPM R1,Z+ MOVW R22,R30 MOVW R30,R0 __GLOBAL_INI_LOOP: LPM R0,Z+ ST X+,R0 SBIW R24,1 BRNE __GLOBAL_INI_LOOP MOVW R30,R22 RJMP __GLOBAL_INI_NEXT __GLOBAL_INI_END:

ale przecież ja nie chcę tego ręcznie usuwać.

Chcę by wszystko było w pliku C, bez kombinacji.

EM pisze:

A takie coś:

char data; data = *(char*)0x60;

nie działa?

P.

Do tego sluza bity stanu procesora, ktore wskazuja na przyczyne resetu. Zobacz rejestr MCU, bity WDRF, BORF, EXTRF i PORF. Metoda o ktorej piszesz nic nie da, bo zawartosc pamieci RAM dosyc dlugo pozostaje nieuszkodzona. Co wiecej, jesli w pamieci stale jest ta sama wartosc to jest spora szansa, ze po wlaczeniu zasilania ta wartosc ciagle tam bedzie. Ot taki ciekawy efekt pamieciowy.

T.M.F. pisze: >> Otóż potrzebuję na początku programu sprawdzić wartość 2 komórek >> pamięci RAM. Zakładam, że komórki te mają wartość taka jak poprzednio, >> jeśli napięcie zasilania nie spadło poniżej pewnego poziomu. Podobnie >> robię w PICach i to się dobrze sprawdza. >

Tak na prawdę to potrzebuję rozróżnić, czy przerwa w zasilaniu była dłuższa niż np. 1-2 sekundy, czy nie. Zakładam, że jeśli zapiszę w jednej komórce jakąś wartość i w innej jej negację, to odczyt tych dwóch komórek pozwoli stwierdzić, że jeżeli wpisy są komplementarne, to prawdopodobnie przerwa w zasilaniu była krótka - czytaj zasilanie nie spadło do jakiegoś granicznego progu.

Jeśli uda mi się w końcu czytać te komórki bez inicjalizacji to sprawdzę jak się zachowują AVRki pod tym względem. Popróbuję z tym wskaźnikiem.

Jak wspominałem podobny mechanizm mam na PICu i działa bez problemów.

Co do hardware nie mam niczego, co mógłbym wykorzystać - to jest w istniejącym układzie. Istnieje tam kondensator podtrzymujący zasilanie - może to być 10u, nie sprawdzałem dokładnie i to jest wszystko.

Piotrne pisze:

Witam Dzięki

Rozumiem, że ten kawałek odczytuje z komórki o adresie 0x60

A jak zapisać do takiej komórki, nie inicjalizując jej jakoś?

EM pisze:

Jeśli tamto działa, to tak: char data; data = 123; *(char*)0x60 = data;

Pozdrawiam P.

ALe to tylko odczyta komorke o adresie 0x60, ale nie spowoduje, ze zostanie ona zarezerwowana. W efekcie kompilator umiesci tam pierwsza lepsza zmienna i nic z tego nie wyniknie. W AVR-gcc wystarczy stworzyc globalna zmienna niestatyczna, kompilator nie inicjalizuje takich zmiennych.

T.M.F. pisze:

Jeżeli zmienna wpadnie do sekcji .bss - to zostanie automatycznie wyzerowana. Jeżeli potrzeba zmiennej, która nie będzie inicjowana, trzeba skorzystać z dobrodziejstwa sekcji ".noinit".

Adam Dybkowski pisze:

W takim przykladzie: void main() { int a;

if(a==costam) DoSomething(); }

Zmienna a nie bedzie inicjalizowana. Poniewaz za kazdym razem trafia w to samo miejsce programu jej wartosc bedzie zachowana pomiedzy uruchomieniami. Oczywiscie kompilator wyrzuci ostrzezenie, ze uzywamy niezainicjalizowanej zmiennej, ale w koncu o to nam chodzi.

T.M.F. pisze:

Ale to mi powinno wystarczyć, sprawdzę w listingu, czy nie nastąpi jakiś konflikt z wykorzystywaną komórką. Program jest prosty i akurat zasobów RAM prawie nie wykorzystuje.

T.M.F. pisze:

Bardzo ciekawa propozycja jak dla mnie. Rozumiem, że program przy każdym uruchomieniu natrafi na ten sam obszar w RAM, a nie powinien on być inicjowany - zerowany. Nie stanowi natomiast problemu, że tak na prawdę nie wiem jaki to będzie adres. Wcześniej próbowałem void main() { char data @0x60;; .... }

ale taki podanie adresu działa tylko dla zmiennych globalnych.

Sprawdzam...

Dla lokalnych statycznych też chyba powinno ;).... ale nie o to chodzi :D

T.M.F. pisze:

Zmienna "a" jest w powyższym przykładzie lokalna i oczywiście trafi na stos lub zostanie upchnięta w rejestrze. W twoim przykładzie tak się składa, że zawsze trafi w to samo miejsce (bo jest w funkcji main - wywoływanej zawsze tak samo i z tego samego miejsca) ale gdyby była w innej funkcji to już nie będzie tak różowo.

Witam Zgodnie z sugestiami zastosowałem coś takiego:

void main(void) { unsigned char short_off_indicator[2];

...

if (short_off_indicator[0] == ~ short_off_indicator[1]) {short_off()) else long_off()

...

short_off_indicator[0] = next_mode; short_off_indicator[1] = ~ next_mode;

... }

Ogólnie działa dobrze :)

Dziękuję za szybką i konkretną pomoc

EM pisze:

W przypadku PICa i kompilatora hitech słuzy do tego modyfikator persistent umieszczony w deklaracji zmiennej; może u Ciebie podobnie będzie

Pozdr jp

EM pisze:

[...]

Obyś się nie zdziwił, gdy po zmianie opcji optymalizatora wyjdzie co innego, niż obecnie. Zdecydowanie polecam jeszcze doczytanie o sekcji ".noinit", chociażby w dokumentacji avr-libc.

Adam Dybkowski pisze:

Coz moze wyjsc. Zeby to sie nie zoptymalizowalo w jakis dziwny sposob wystarczy dodac volatile.

Join the Discussion

Have something to add? Share your thoughts — no account required.

Didn't find your answer?

Ask the community — no account required