Aktyw Forum
Zarejestruj się na forum.ep.com.pl i zgłoś swój akces do Aktywu Forum. Jeśli jesteś już zarejestrowany wystarczy, że się zalogujesz.
Sprawdź punkty Zarejestruj sięUmieszczenie tablicyuint w pamieci flash w AVR-GCC
Moderatorzy:Jacek Bogusz, procesorowiec, r-mik, Moderatorzy
Cześć.
Możecie mi powiedzeć jak a AVR-GCC umiescic tablice w pamieci flash a nastepnie odczytac ją. Dane są w w formacie Unsgned int z zkresem od 0 do 34000.
Może pytanie jest banalne ale natknąłem się na pewne trudności i proszę Was o pomoc.
Spotkałem kilka mozliwości zapisu i nie wiem czym sie różnią.
Sławek.
P.S.
Przy okazji jeszcze chciałbym sie spytać jak to jest np w przypadku np. obsługi lcd. Zwyke tworzy się sie dwie funkcje wyswietlajace tekst jedna dla danych odczytywanych z RAM a druga z flash.
Czy możecie mi powiedzieć dlaczego dwie i jak powinny wyglądać.
Jest to tylko kwestią przypomnienia bo troche sie zamieszałem, więc pytanie może się wydawac dziwne, ale proszę o pomoc.
Możecie mi powiedzeć jak a AVR-GCC umiescic tablice w pamieci flash a nastepnie odczytac ją. Dane są w w formacie Unsgned int z zkresem od 0 do 34000.
Może pytanie jest banalne ale natknąłem się na pewne trudności i proszę Was o pomoc.
Spotkałem kilka mozliwości zapisu i nie wiem czym sie różnią.
Sławek.
P.S.
Przy okazji jeszcze chciałbym sie spytać jak to jest np w przypadku np. obsługi lcd. Zwyke tworzy się sie dwie funkcje wyswietlajace tekst jedna dla danych odczytywanych z RAM a druga z flash.
Czy możecie mi powiedzieć dlaczego dwie i jak powinny wyglądać.
Jest to tylko kwestią przypomnienia bo troche sie zamieszałem, więc pytanie może się wydawac dziwne, ale proszę o pomoc.
-
- -
- Posty:175
- Rejestracja:10 paź 2003, o 20:44
- Lokalizacja:Białystok
- Kontaktowanie:
Re: Umieszczenie tablicyuint w pamieci flash w AVR-GCC
Np. tak :Możecie mi powiedzeć jak a AVR-GCC umiescic tablice w pamieci flash a nastepnie odczytac ją.
Kod: Zaznacz cały
#include <avr/pgmspace.h>
...............
uint Tablica[] PROGMEM = {0,100,1000,10000,30000};
uint Element;
.................
Element=pgm_read_word(&Tablica[3]);
Ja spotkałem jeszcze takie coś
Próbowałem też odczytać poprzez podstawienie elementu tablicy do danej i nie powstał błąd kompilacji tzn
Nie wygenerował błędu?
a co oznacza
A mogę prosić o to co pytałem o lcd.
Kod: Zaznacz cały
pgm_uint16_t tablica[10];
Kod: Zaznacz cały
uint16_t dana;
prog_uint16_t talica[10];
dana=tablica[1];
Nie wygenerował błędu?
a co oznacza
Kod: Zaznacz cały
pgm_read_word
-
- -
- Posty:175
- Rejestracja:10 paź 2003, o 20:44
- Lokalizacja:Białystok
- Kontaktowanie:
Proponuję jednak zajrzeć do manuala avr-libc -> Library reference ->Próbowałem też odczytać poprzez podstawienie elementu tablicy do danej i nie powstał błąd kompilacji tznKod: Zaznacz cały
uint16_t dana; prog_uint16_t talica[10]; dana=tablica[1];
Nie wygenerował błędu?
a co oznaczaA mogę prosić o to co pytałem o lcd.Kod: Zaznacz cały
pgm_read_word
avr/pgmspace.h Program Space String Utilities.
Nie wszystko będzie od razu jasne ale przynajmniej obejrzysz czym
dysponują biblioteki.
Tam od razu sprawdzisz, że typ prog_uint16_t jest dokładnie tym samym
co uint16_t PROGMEM - utworzonym poprzez typedef.
Jeśli masz ochotę - tworzysz sobie zupełnie własny ( z nazwy, ale
identyczny w działaniu ) typ np.
typedef uint PROGMEM Calkowita_bez_znaku_w_pamieci_flash;
i zamiennie go używasz :
Calkowita_bez_znaku_w_pamieci_flash Tablica2[] = {20,120,1200,12000,34000};
W manualu wyjaśni się też od razu, że pomocnicze funkcje pgm_read_byte
czy pgm_read_word służą do odczytania jedno- lub dwubajtowej zawartości
flash spod podanego adresu. W przypadku tablicy jako argument podajemy adres
potrzebnego elementu tablicy np. &Tablica[4] itd.
( Natomiast stała we flashu musi mieć początkowe wartości.
Zapis uint PROGMEM tablica[10]; nie ma sensu logicznego - bo co odczytasz
z zostawionego pustego miejsca we flashu ?. Zresztą u mnie kompilator tego
nie puszcza i zgłasza błąd. )
I ponieważ w avr-gcc inaczej odwołujemy się do ram ( bezpośrednio ) a
inaczej do flash ( za pomocą pomocniczych funkcji jw ) często przy
obsłudze peryferiów ( lcd, uart itd. ) pisze się dwie wersje funkcji :
jedna pobiera dane bezpośrednio z ram a druga jest przystosowana
do ściągania danych z flash. BTW to wcale nie jest konieczność. Możesz
np. przeznaczyć do współpracy z lcd oddzielny bufor ram i wtedy używasz
zawsze jednakowego sposobu wyświetlania ( pobieranie danych tylko
z tego bufora ), natomiast do bufora wcześniej ładujesz te dane skąd tylko
chcesz ( flash, eeprom, zewnętrzny DataFlash itp. )
Pozdrowienia Jurek S.
oczywiście ze zapis
nie ma sensu ja nie pisałem reszty
CZy mogę jeszcze prosć o podanie gdzie moge poczytać sobie tego manala.
A dlaczego dział takie przypisanie zwykłeczyli
bez tego .
Kod: Zaznacz cały
uint PROGMEM tablica[10];
CZy mogę jeszcze prosć o podanie gdzie moge poczytać sobie tego manala.
A dlaczego dział takie przypisanie zwykłeczyli
Kod: Zaznacz cały
uint16_t dana;
prog_uint16_t talica[10];
dana=tablica[1];
Kod: Zaznacz cały
pgm_read_word
-
- -
- Posty:175
- Rejestracja:10 paź 2003, o 20:44
- Lokalizacja:Białystok
- Kontaktowanie:
Manual jest w wielu miejscach, online np.CZy mogę jeszcze prosć o podanie gdzie moge poczytać sobie tego manala.
A dlaczego dział takie przypisanie zwykłeczylibez tegoKod: Zaznacz cały
uint16_t dana; prog_uint16_t talica[10]; dana=tablica[1];
.Kod: Zaznacz cały
pgm_read_word
http://www.nongnu.org/avr-libc/user-man ... space.html
Można tez pościągać w różnych wersjach ( html, pdf )
http://download.savannah.gnu.org/releases/avr-libc/
Działanie powyższego kodu to "robota" optymalizatora.
Jeśli napiszesz np.
Kod: Zaznacz cały
prog_uint16_t Tablica1[] = {10,20,30,40,50};
Kod: Zaznacz cały
Element=Tablica1[2];
w trakcie kompilacji. Optymalizator korzysta z tego, wyciąga
spod adresu komórki tablicy wartość i ładuje ją bezpośrednio do
zmiennej bez żadnych kodów pobierania z flasha :
Kod: Zaznacz cały
Element=Tablica1[2];
ec: 8e e1 ldi r24, 0x1E ; 30
ee: 90 e0 ldi r25, 0x00 ; 0
f0: 90 93 0d 01 sts 0x010D, r25
f4: 80 93 0c 01 sts 0x010C, r24
tablicy użyjesz indeksu ustalanego programowo :
Kod: Zaznacz cały
uint Indeks;
.....
Indeks=2;
Element=Tablica1[Indeks];
do obszaru ram zamiast flash ( avr-gcc tak ma - było to
wielokrotnie omawiane w różnych miejscach ). Nie będzie
zgłaszany błąd ale oczywiście program nie zadziała:
Kod: Zaznacz cały
Indeks=2;
e0: 82 e0 ldi r24, 0x02 ; 2
e2: 90 e0 ldi r25, 0x00 ; 0
e4: 90 93 0b 01 sts 0x010B, r25
e8: 80 93 0a 01 sts 0x010A, r24
Element=Tablica1[Indeks];
ec: e0 91 0a 01 lds r30, 0x010A
f0: f0 91 0b 01 lds r31, 0x010B
f4: ee 0f add r30, r30
f6: ff 1f adc r31, r31
f8: e5 5c subi r30, 0xC5 ; 197
fa: ff 4f sbci r31, 0xFF ; 255
fc: 80 81 ld r24, Z
fe: 91 81 ldd r25, Z+1 ; 0x01
100: 90 93 0d 01 sts 0x010D, r25
104: 80 93 0c 01 sts 0x010C, r24
Pozdrowienia Jurek S.
Prawda na to nie zwróciłem uwagi. Sprawdziłem w AvrStudio.
Jest tam do wyboru kilka funkcji
word dword oraz near lub fara co jam mam wybrać dla Atmega128.
Jak mam odróżnić near od far.
A czy byte word oraz dword są ze znakiem czy bez i ile wynosi dword, bo rozumiem ze word to 16 bitów.
Jest tam do wyboru kilka funkcji
Kod: Zaznacz cały
pgm_read_byte_near
word dword oraz near lub fara co jam mam wybrać dla Atmega128.
Jak mam odróżnić near od far.
A czy byte word oraz dword są ze znakiem czy bez i ile wynosi dword, bo rozumiem ze word to 16 bitów.
-
- -
- Posty:175
- Rejestracja:10 paź 2003, o 20:44
- Lokalizacja:Białystok
- Kontaktowanie:
near obsługuje adresy do 64k a far - powyzej.Prawda na to nie zwróciłem uwagi. Sprawdziłem w AvrStudio.
Jest tam do wyboru kilka funkcjiKod: Zaznacz cały
pgm_read_byte_near
word dword oraz near lub fara co jam mam wybrać dla Atmega128.
Jak mam odróżnić near od far.
A czy byte word oraz dword są ze znakiem czy bez i ile wynosi dword, bo rozumiem ze word to 16 bitów.
Ponieważ atrybut PROGMEM działa z załozenia tylko do 64k
- użyjemy near ( które zresztą jest zdefiniowane jako domyślne
czyli wystarczy np. pgm_read_byte )
byte = uint8_t
word=uint16_t
dword=uint32_t
Pozdrowienia Jurek S.
-
- -
- Posty:175
- Rejestracja:10 paź 2003, o 20:44
- Lokalizacja:Białystok
- Kontaktowanie:
Linker lokuje stałe PROGMEM zaraz na początku - po wektorach przerwań.a skąd ja mam wiedzieć czy zostanie to ulokowane na początku pamięci czy gdzieś powyżej 64K.
Tak więc near ( z instrukcjami lpm ) będzie zazwyczaj OK.
Problem może się pojawić dopiero przy jakichś wielkich ilościach (>64k) stałych.
Także jeśli zechcesz użyć stałych w kodzie bootloadera umieszczonym na końcu
flasha - tam już będą konieczne funkcje far ( z instrukcjami elpm ).
Pozdrowienia Jurek S.
Kto jest online
Użytkownicy przeglądający to forum: Obecnie na forum nie ma żadnego zarejestrowanego użytkownika i 13 gości