AT91SAM7S... CrossStudio i zmienne
ELP - 24-11-2006 17:45
AT91SAM7S... CrossStudio i zmienne Wiam wszystkich.
Może ktoś podpowie, w jaki sposób zadeklarować w środowisku j.w. zmienną
globalną, która nie będzie inicjowana w momencie startu programu. Muszę
wyeliminować jej zerowanie w przypadku zadziałania watchdog`a.
Wiem, że "help" twoim przyjacielem, ale sprawa jest na "wczoraj". Proszę o
wyrozumiałość i nie odsyłanie do "F1" :-)
Pozdrawiam
Adam Dybkowski - 25-11-2006 00:45
ELP napisał(a):
> Może ktoś podpowie, w jaki sposób zadeklarować w środowisku j.w. zmienną
> globalną, która nie będzie inicjowana w momencie startu programu. Muszę
> wyeliminować jej zerowanie w przypadku zadziałania watchdog`a.
Polecamy przejście na gcc (np. pakiet gnuarm).
Wystarczy przenieść zmienną do niestandardowej sekcji (cała sekcja .bss
jest zerowana przy starcie) i dodać taką sekcję w pliku linkera.
unsigned int mojaflaga __attribute__ ((section (".noinit"));
Ewentualnie możesz "na sztywno" wymyślić jakiś adres, np. pod koniec
wewnętrznej pamięci RAM i z tamtej komórki korzystać. Pamiętaj wtedy o
potrzebnym ograniczeniu zakresu działania malloc'a (dokładniej mówiąc
sbrk) aby sterta nie zjadła twojej zmiennej.
unsigned int *mojaflaga = (unsigned int *) 0x12345678; // (wstaw adres)
*mojaflaga = 7;
Zrób bardziej skomplikowany system flag - bo oczywiście przy pierwszym
włączeniu zasilania w RAMie będą krzaki i twoja flaga akurat może się
okazać ustawiona we właściwy sposób. Skutecznym wyjściem jest opatrzenie
zestawu danych niekasowanych jakimś nagłówkiem (np. słowem 0xabcd1234) i
zakończenie sumą kontrolną CRC32 liczoną z całego zabezpieczanego bloku.
Najlepszym rozwiązaniem jest jednak odczytanie z rejestru powodu resetu
procesora i na tej podstawie sprawdzenie, czy reset był w wyniku
zadziałania wewnętrznego watchdoga. Oczywiście to odpada gdy masz
watchdoga na zewnątrz i nie da się odróżnić resetu przyciskiem od resetu
watchdogiem.
--
Adam Dybkowski
http://www.amwaw.edu.pl/~adybkows/Uwaga: przed wysłaniem do mnie maila usuń cyfry z adresu.
Elektrolot - 25-11-2006 07:46
Adam Dybkowski napisał(a):
> ELP napisał(a):
>
>> Może ktoś podpowie, w jaki sposób zadeklarować w środowisku j.w.
>> zmienną globalną, która nie będzie inicjowana w momencie startu
>> programu. Muszę wyeliminować jej zerowanie w przypadku zadziałania
>> watchdog`a.
>
> Polecamy przejście na gcc (np. pakiet gnuarm).
CrossStudio korzysta właśnie z GCC.
pzdr
ELP - 25-11-2006 09:45
> Polecamy przejście na gcc (np. pakiet gnuarm).
> Wystarczy przenieść zmienną do niestandardowej sekcji (cała sekcja .bss
> jest zerowana przy starcie) i dodać taką sekcję w pliku linkera.
>
> unsigned int mojaflaga __attribute__ ((section (".noinit"));
Jak kolega poniżej napisał, CrossStudio korzysta z GCC.
Nie wiem jednak jak dodać taką sekcję do pliku linkera. Może jakiś
przykład?
> Ewentualnie możesz "na sztywno" wymyślić jakiś adres, np. pod koniec
> wewnętrznej pamięci RAM i z tamtej komórki korzystać. Pamiętaj wtedy o
> potrzebnym ograniczeniu zakresu działania malloc'a (dokładniej mówiąc
> sbrk) aby sterta nie zjadła twojej zmiennej.
>
> unsigned int *mojaflaga = (unsigned int *) 0x12345678; // (wstaw adres)
>
> *mojaflaga = 7;
To faktycznie działa, ale ja tak na prawdę potrzebuję kilkadziesiąt takich
zmiennych, no i w tym momencie robi się to troszeczkę upierdliwe
(wyliczanie adresów - łatwo o pomyłkę).
> Najlepszym rozwiązaniem jest jednak odczytanie z rejestru powodu resetu
> procesora i na tej podstawie sprawdzenie, czy reset był w wyniku
> zadziałania wewnętrznego watchdoga.
Właśnie tak to ma być zrobione.
Pozdrawiam
Adam Dybkowski - 26-11-2006 01:45
ELP napisał(a):
>> Wystarczy przenieść zmienną do niestandardowej sekcji (cała sekcja
>> .bss jest zerowana przy starcie) i dodać taką sekcję w pliku linkera.
> Nie wiem jednak jak dodać taką sekcję do pliku linkera. Może jakiś
> przykład?
Zobacz, jak jest zrobiona obecnie np. sekcja .bss i wyrzuć z jej
deklaracji wszystkie niepotrzebne definicje adresów (początek i koniec
sekcji .bss - wykorzystywane do wyczyszczenia jej przy starcie). W pliku
linkera (.ld) w bloku SECTIONS powinieneś dodać coś w tym rodzaju:
..noinit :
{
*(.noinit)
} >ram
Oczywiście "ram" zastąp nazwą obszaru pamięci, który definiujesz na
początku swojego pliku linkera (w bloku MEMORY).
--
Adam Dybkowski
http://www.amwaw.edu.pl/~adybkows/Uwaga: przed wysłaniem do mnie maila usuń cyfry z adresu.
ELP - 26-11-2006 15:45
>>> Wystarczy przenieść zmienną do niestandardowej sekcji (cała sekcja
>>> .bss jest zerowana przy starcie) i dodać taką sekcję w pliku linkera.
>
>> Nie wiem jednak jak dodać taką sekcję do pliku linkera. Może jakiś
>> przykład?
>
> Zobacz, jak jest zrobiona obecnie np. sekcja .bss i wyrzuć z jej
> deklaracji wszystkie niepotrzebne definicje adresów (początek i koniec
> sekcji .bss - wykorzystywane do wyczyszczenia jej przy starcie). W pliku
> linkera (.ld) w bloku SECTIONS powinieneś dodać coś w tym rodzaju:
>
> .noinit :
> {
> *(.noinit)
> } >ram
>
> Oczywiście "ram" zastąp nazwą obszaru pamięci, który definiujesz na
> początku swojego pliku linkera (w bloku MEMORY).
>
Dzięki za podpowiedź. Będę próbował tego sposobu.
Troszkę poszukałem i znalazłem zadeklarowane sekcje, które nie są
inicjowane przy starcie uC. Dla programu ładowanego do RAM jest to sekcja
".fast_load", a dla ładowanego do Flash ".fast_run". Malutkie makro
uzależniające deklarację zmiennych w zależności od tego, gdzie jest
program ładowany (Ram, Flash) i efekt jest 100%owy. Może to nie "po
bożemu", ale diała :-)
Dzięki wzystkim za pomoc.
Pozdrawiam.
Adam Dybkowski - 27-11-2006 01:45
ELP napisał(a):
> Troszkę poszukałem i znalazłem zadeklarowane sekcje, które nie są
> inicjowane przy starcie uC. Dla programu ładowanego do RAM jest to
> sekcja ".fast_load", a dla ładowanego do Flash ".fast_run". Malutkie
> makro uzależniające deklarację zmiennych w zależności od tego, gdzie
> jest program ładowany (Ram, Flash) i efekt jest 100%owy. Może to nie "po
> bożemu", ale diała :-)
Bardzo dobry sposób. Jeżeli twój plik linkera już definiuje sekcje,
które nie są zmieniane przy starcie programu - to najlepiej właśnie z
nich skorzystać.
--
Adam Dybkowski
http://www.amwaw.edu.pl/~adybkows/Uwaga: przed wysłaniem do mnie maila usuń cyfry z adresu.
AK - 27-11-2006 12:46
ELP napisał(a):
> Wiam wszystkich.
>
> MoÄąźe ktoÄąďż˝ podpowie, w jaki sposÄłb zadeklarowaĂďż˝ w Äąďż˝rodowisku j.w.
> zmiennĂďż˝ globalnĂďż˝, ktÄłra nie bĂďż˝dzie inicjowana w momencie startu
> programu. MuszĂďż˝ wyeliminowaĂďż˝ jej zerowanie w przypadku zadziaÄąďż˝ania
> watchdog`a.
W prosty sposob nie da sie tego zrobic.
Kazda zmienna globalne jest inicjowana - na 0 lub wartosc wpisana w
programie.
Jedyne co mi przychodzi do glowy, to zarezerwowanie np. czterech
bajtow w pamieci poprzez skrypt linkera i odwolywanie sie do tego
obszaru poprzez wskaznik na unsigned long.
Ale jak to nie bedzie inicjowane, to wtedy po wlaczeniu zasilania moze
byc dowolna wartosc. Dosc ryzykowny sposob na rozpoznanie resetu watchdoga.
A swoja droga, w tym procesorze da sie odczytac powod resetu.
Zobacz na strone 69 dokumentacji - rejestr RSTC_SR.
Ewentualnie mozna w startup-ie spawdzic powod resetu i jesli to
watchdog, to pomijamy inicjalizacje tej zmiennej.
W kazdym razie raczej nie da rady bez grzebania w plikach startowych.
Pozdr
AK
Artur P - 27-11-2006 12:46
ELP napisał(a):
> Może ktoś podpowie, w jaki sposób zadeklarować w środowisku j.w. zmienną
> globalną, która nie będzie inicjowana w momencie startu programu. Muszę
> wyeliminować jej zerowanie w przypadku zadziałania watchdog`a.
A może wrzucić ją do innej sekcji niż .data przez np. __attribute__
coś tam, i tylko odpowiednio zmodyfikować plik linkera aby zamapował tą
sekcję w pamięci ram.
--
Pozdrawiam,
Artur Płatek
zanotowane.pldoc.pisz.plpdf.pisz.plkonstruktor.keep.pl