logo elektroda
logo elektroda
X
logo elektroda
REKLAMA
REKLAMA
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

Jak ustawić rozmiar stosu w kompilatorze avr-gcc (WinAvr).

LuznyTomasz 02 Maj 2005 19:19 3633 13
REKLAMA
  • #1 1455743
    LuznyTomasz
    Poziom 15  
    Posty: 204
    Pomógł: 13
    Ocena: 1
    Zauważyłem że kompilator umieszcza moje zmienne pod koniec pamięci SRAM. Podczas debugowania programu zauważyłem typowe objawy wysypania się stosu - program nie wracał w odpowiednie miejsce po zakończeniu funkcji. Ponadto dane znajdujące się pod koniec SRAM wyświetlane są na LCD. Pomimo, że zostały one wyczyszczone na początku programu po pewnym czasie zawierają pewne dane które widać na wyświetlaczu. W jaki sposób programowo (bądź w ustawieniach WinAvr) zadeklarować obszar stosu?

    PS Piszę oczywiście w C

    Problem się trochę rozwiązał...wykorzystuje całą dostępną pamięć SRAM i jeszcze trochę :) Czy stałe muszę zapisywać w pamięci danych? Programuje wyświetlacz LCD Nokii i potrzebuje zadeklarowac sobie wszystkie znaki ale potem w programie nie ma potrzeby ich zmieniać. Zatem gdzie i jak to umieścić?

    static const byte FontLookup [][5] =
    {
    { 0x00, 0x00, 0x00, 0x00, 0x00 }, // sp
    { 0x00, 0x00, 0x2f, 0x00, 0x00 }, // !
    { 0x00, 0x07, 0x00, 0x07, 0x00 }, // "
    .......

    Stos też chciałbym jakoś zadeklarować...
  • REKLAMA
  • Pomocny post
    #2 1456054
    juntom
    Poziom 19  
    Posty: 216
    Pomógł: 35
    Ocena: 27
    Lepiej wykorzystaj do tego celu pamiec programu , ewentualnie eeprom. Sposob deklaracji tablic dla winavr :
    dla eeprom :
    #include <avr/eeprom.h>
    #define EEPROM __attribute__ ((section (".eeprom")))
    unsigned char temp [20] EEPROM ={1,2,3,4,};

    dla pamieci programu :
    #include <avr/pgmspace.h>
    static unsigned char temp_1 [2] PROGMEM = {1,2,3,4};
  • #3 1456073
    Zbych_
    Poziom 25  
    Posty: 456
    Pomógł: 81
    Ocena: 6
    Niestety GCC nie rozróżnia obszarów pamięci (zna tylko architekturę von Neumanna), dlatego oprócz odpowiedniej deklaracji zmiennych trzeba też używać specjalnych makr do odczytu tychże zmiennych. Wszystko jest opisane w dokumentacji do avr-libc.
  • #4 1460262
    LuznyTomasz
    Poziom 15  
    Posty: 204
    Pomógł: 13
    Ocena: 1
    Tanlicę FontLookup umieściłem w pamięci programu. Mam teraz problem z jej odczytaniem!

    Polecenie c = pgm_read_byte_near(FontLookup[ch - 32][i] << 1); nie czyta tablicy tylko jakieś śmieci.
  • REKLAMA
  • #6 1460456
    LuznyTomasz
    Poziom 15  
    Posty: 204
    Pomógł: 13
    Ocena: 1
    Problem w tym że nie wiem dokładnie czemu służy to <<1.
    Gdy talbica znajdowała się w pamięci programu była odczytywana w taki właśnie sposób c = FontLookup[ch - 32][i] << 1; Ja zmieniłem tylko miejsce w którym znajduje się tablica FontLookup i teraz nie mogę się do niej dostać.

    EDIT:<<1 w sumie przesuwa tylko odczytaną zawartość tablicy. Usunięcie tej operacji nie zmienia niczego - dalej czytam jakieś śmieci (dokładniej wartość 0x0c)
  • #7 1460561
    LordBlick
    VIP Zasłużony dla elektroda
    Posty: 5438
    Pomógł: 549
    Ocena: 69
    <<1 to przesunięcie bitowe w lewo, czyli pomnożenie przez 2. Używa się go w w/w przypadku, bo adres w pamięci programu dotyczy danych 16bit, a odczyt zawartości poprzez adresowanie rejestrem Z i instrukcją lpm jest 8bit. A zadałem takie pytanie, bo mozliwe, że w tym makro jest to już uwzględnione.
  • REKLAMA
  • #8 1460765
    LuznyTomasz
    Poziom 15  
    Posty: 204
    Pomógł: 13
    Ocena: 1
    Musze powiedzieć że masz nosa :) źle postawiłem nawias
    c = pgm_read_byte_near(FontLookup[ch - 32][i]) << 1;
    Dane w tablicy zawierają piksele które trzeba zapalic w wyświetlaczu z nokii 3310. To przesunięcie zapewnia odstęp pomiędzy liniami. Nie ma natomiast nic wspólnego z adresowaniem.

    Jak znaleść adres pod którym znajduje się moja tablica? Próbując wyświetlić dwa razy wyraz "Halo" widze 2 krotnie powtrzającą się sekwencję szlaczków, jednak przypomina to mi jedynie hebrajski. Problem więc leży w złym zaadresowaniu.
  • #9 1460800
    LordBlick
    VIP Zasłużony dla elektroda
    Posty: 5438
    Pomógł: 549
    Ocena: 69
    Po prostu programuję w asm i tam adresy etykiet w pamięci programu są dla danych dwa razy większe, ze względów, które wymieniłem wyżej. Próbowałeś symulacji w AVRStudio ?
  • REKLAMA
  • #10 1460818
    LuznyTomasz
    Poziom 15  
    Posty: 204
    Pomógł: 13
    Ocena: 1
    Tak oczywiście. Tylko że w polu location dla tej tablicy mam wpisane SRAM...a znajduje się z pewnością w pamięci programu (co do tego nie mam wątpliwości).
  • Pomocny post
    #11 1460823
    GienekS
    Poziom 32  
    Posty: 1971
    Pomógł: 139
    Ocena: 15
    LuznyTomasz napisał:
    Tanlicę FontLookup umieściłem w pamięci programu. Mam teraz problem z jej odczytaniem!

    Polecenie c = pgm_read_byte_near(FontLookup[ch - 32][i] << 1); nie czyta tablicy tylko jakieś śmieci.

    Polecenie c = pgm_read_byte_near(&FontLookup[ch - 32][i]);

    Tak powinno zadziałać.
  • Pomocny post
    #12 1460825
    LordBlick
    VIP Zasłużony dla elektroda
    Posty: 5438
    Pomógł: 549
    Ocena: 69
    LuznyTomasz napisał:
    Tak oczywiście. Tylko że w polu location dla tej tablicy mam wpisane SRAM...a znajduje się z pewnością w pamięci programu (co do tego nie mam wątpliwości).
    No to powinno czytać z pamięci programu użyj "&"
  • #13 1460838
    LuznyTomasz
    Poziom 15  
    Posty: 204
    Pomógł: 13
    Ocena: 1
    Ech...ty to jednak jesteś debeściak :)

    Edit: A wie może ktoś co oznacza to "near"?
  • #14 1463193
    robkry
    Poziom 15  
    Posty: 59
    Pomógł: 11
    Ocena: 5
    No cóż wystarczy poczytać dokumentację... objaśniam w dużym skrócie dla avrlibc:

    nazwa_funkcji_near - oznacza używanie adresowania 16 bitowego (bliskiego) - większość AVR'ów (do 64kB pamięci programu)

    nazwa_funkcji_far - oznacza używanie adresowania 32 bitowego - AVR'y z pamięcią programu 128kB i więcej - są już takie :)

    Cytat:

    #define pgm_read_byte_near ( address_short ) __LPM((uint16_t)(address_short))

    Read a byte from the program space with a 16-bit (near) address.

    Note:
    The address is a byte address. The address is in the program space


    a tak odnośnie wątku:
    lepiej zamiast pgm_read_byte_near użyć pgm_read_byte - kompilator sam sobie wybierze odpowiednią funkcję (makro) w zależności od użytego mikrokontrolera....

Podsumowanie tematu

✨ W dyskusji poruszono problem ustawienia rozmiaru i lokalizacji stosu w kompilatorze avr-gcc (WinAvr) oraz zarządzania pamięcią SRAM i pamięcią programu (flash) w mikrokontrolerach AVR. Zauważono, że zmienne umieszczane są pod koniec SRAM, co prowadzi do przepełnienia stosu i błędów w działaniu programu. Zalecane jest przechowywanie stałych danych, takich jak tablice znaków do wyświetlacza LCD, w pamięci programu (flash) lub EEPROM, aby oszczędzić pamięć SRAM. Przykłady deklaracji tablic w pamięci programu i EEPROM podano z użyciem atrybutów __attribute__((section(".eeprom"))) oraz PROGMEM i odpowiednich nagłówków avr/pgmspace.h i avr/eeprom.h. Omówiono także prawidłowy sposób odczytu danych z pamięci programu za pomocą funkcji pgm_read_byte_near() z poprawnym użyciem operatora adresu (&) i indeksowania tablicy. Wyjaśniono znaczenie sufiksów "near" i "far" w funkcjach odczytu, odnoszących się do rozmiaru adresowania pamięci programu (16-bitowe dla mniejszych AVR, 32-bitowe dla większych). Podkreślono, że kompilator GCC nie rozróżnia obszarów pamięci, dlatego konieczne jest stosowanie specjalnych makr i funkcji z biblioteki avr-libc. Problem z błędnym odczytem danych z pamięci programu wynikał z nieprawidłowego nawiasowania i braku operatora adresu przy wywołaniu pgm_read_byte_near(). Dodatkowo omówiono przesunięcie bitowe
Wygenerowane przez model językowy.
REKLAMA