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

C - Przekazywanie wskaźnika na tablice PROGMEM do funkcji

05 Lip 2015 14:30 2223 15
REKLAMA
  • #1 14825680
    Konto nie istnieje
    Konto nie istnieje  
  • REKLAMA
  • #2 14825896
    tmf
    VIP Zasłużony dla elektroda
    Posty: 14318
    Pomógł: 2090
    Ocena: 2205
    A po co wskaźnik? Nie prościej normalnie - czyli tablica? Kompilator sam sobie z tego zrobi wskaźnik, bo tablice zawsze są przekazywane przez referencję, a nie wartość. Kolejna sprawa, że to PROGMEM lepiej zastąpić przez __flash i normalnie indeksować elementy, bez żadnych makr, typu pgm_read_cośtam.
  • #3 14826085
    Konto nie istnieje
    Konto nie istnieje  
  • REKLAMA
  • #4 14826134
    tmf
    VIP Zasłużony dla elektroda
    Posty: 14318
    Pomógł: 2090
    Ocena: 2205
    Ale to przecież nigdy ci nie wyjdzie - bo jeśli zdefiniujesz wskaźnik jako [][] to skąd kompilator ma wiedzieć ile elementów ma tablica? A jest mu to niezbędne do wyliczenia adresu elementu. Z kolei jeśli jawnie podasz ile elementów jest, to wskaźnik będzie niekompatybilny z tablicami o innych rozmiarach. Także rozwiązaniem jest jawne przekazywanie do funkcji przynajmniej liczby elementów w wierszu. Można to rozwiązać automatycznie przy pomocy makra, które rozwinie się do postaci &tablica, sizeof(tablica[]).
  • #5 14826204
    Konto nie istnieje
    Konto nie istnieje  
  • REKLAMA
  • #6 14826308
    tmf
    VIP Zasłużony dla elektroda
    Posty: 14318
    Pomógł: 2090
    Ocena: 2205
    Bo przekazujesz element o indeksie [i6][0], a nie [i6][1], a tak naprawdę powinno temu towarzyszyć jakieś ostrzeżenie, bo zamiast elementu o typie int dajesz wskaźnik na tablicę jednowymiarową int. Druga sprawa, że jeśli tablica jest we FLASH to żadne z tych wywołań nie powinno zwracać prawidłowych elementów, bo dostęp do nich jest nieprawidłowy - dane są czytane z SRAM a nie z FLASH.
  • #7 14826782
    Konto nie istnieje
    Konto nie istnieje  
  • #8 14826888
    BeginEnd
    Poziom 14  
    Posty: 85
    Pomógł: 10
    Ocena: 11
    tmf napisał:
    Druga sprawa, że jeśli tablica jest we FLASH to żadne z tych wywołań nie powinno zwracać prawidłowych elementów, bo dostęp do nich jest nieprawidłowy - dane są czytane z SRAM a nie z FLASH.


    A skąd pewność że jakikolwiek odczyt ma miejsce? Obstawiam, że kompilator/linker sobie to optymalizuje (bo po co czytać skoro wartości mam podane na tacy?).

    Co do adresowania to sprawdź czy adres button_pos_1 nie jest większy niż 64KB. Być może będziesz potrzebował użyć PROGMEM/uint_farptr_t. Przestrzeń adresowa AVR nie jest liniowa i pointery do pamięci SRAM nie działają zawsze tak jak pointer do FLASH (PROGMEM)

    Zobacz sobie deklaracje funkcji z biblioteki C operujących na danych we FLASHu np: strlen_PF() to zrozumiesz gdzie popełniasz błąd.
  • REKLAMA
  • #9 14827148
    tmf
    VIP Zasłużony dla elektroda
    Posty: 14318
    Pomógł: 2090
    Ocena: 2205
    Mictronic napisał:

    Ale co w przypadku gdy chce przejsc na ekran drugi i zaladowac buttony na pozycjach z tablicy drugiej? Chcialem przekazac jakos elegancko wskaznik tablicy do funkcji button_init.


    Jeśli indeksy poszczególnych tablic są takie same, a wydaje się, że w twoim przypadku są, to musisz po prostu jako argument zdefioniować tablicę o wskazanej liczbie wymiarów i takiej samej liczbie elementów. Obojętnie czy będziesz to przekazywał przez wskaźnik, czy przez tablicę, która de facto jest wskaźnikiem.

    Dodano po 5 [minuty]:

    BeginEnd napisał:
    tmf napisał:
    Druga sprawa, że jeśli tablica jest we FLASH to żadne z tych wywołań nie powinno zwracać prawidłowych elementów, bo dostęp do nich jest nieprawidłowy - dane są czytane z SRAM a nie z FLASH.


    A skąd pewność że jakikolwiek odczyt ma miejsce? Obstawiam, że kompilator/linker sobie to optymalizuje (bo po co czytać skoro wartości mam podane na tacy?).


    Pewność stąd, że kompilator musi generować poprawny kod, a nie brać sobie wartości z sufitu. Jeśli elementy inicjalizujesz dla tablicy będącej we FLASH, a odwołujesz się do SRAM, to kompilator nie może uznać tego za tożsame.

    BeginEnd napisał:
    Co do adresowania to sprawdź czy adres button_pos_1 nie jest większy niż 64KB. Być może będziesz potrzebował użyć PROGMEM/uint_farptr_t. Przestrzeń adresowa AVR nie jest liniowa i pointery do pamięci SRAM nie działają zawsze tak jak pointer do FLASH (PROGMEM)

    Zobacz sobie deklaracje funkcji z biblioteki C operujących na danych we FLASHu np: strlen_PF() to zrozumiesz gdzie popełniasz błąd.


    Żeby potrzebował farptr (które przy okazji wcale nie jest wskaźnikiem a zwykłym typem 32 bitowym), musiałby mieć w kodzie dane w PROGMEM przekraczające 64 kB, na co nic nie wskazuje. Z ciekawości zapytam - podałbyś jakiś przykład, gdy wskaźnik do SRAM zachowuje się inaczej niż wskaźnik do FLASH? Też przy okazji - klasycznie nie mamy wskaźników do FLASH, stąd konieczność użycia makr pgm i PROGMEM, Tego typou wskaźniki to nowość i wymagają użycia named address spaces, co sugerowałem w pierwszym poście, ale autor jakoś tego nie chce użyć.
  • Pomocny post
    #10 14827198
    Andrzej__S
    Poziom 28  
    Posty: 567
    Pomógł: 182
    Ocena: 65
    W nawiązaniu do porad kolegi tmf proponowałbym coś w tym stylu (być może strach przed kwalifikatorem __flash wynika z braku przykładów kodu :?: :
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Być może to nie jest rozwiązanie optymalne, chodziło mi tylko o pokazanie zasady.
    Czy tak nie jest wygodniej, niż używać pgm_read_xxx()? :)
  • #11 14828878
    Konto nie istnieje
    Konto nie istnieje  
  • Pomocny post
    #12 14829477
    Andrzej__S
    Poziom 28  
    Posty: 567
    Pomógł: 182
    Ocena: 65
    Mictronic napisał:
    Dodam ze pod avrgcc nie odpala bo on nie rozumie czym jest __flash. Avrstudio oferuje o wiele lepsze mozliwosci.

    AVR Studio też raczej "nie rozumie". Chodziło Ci chyba raczej o Atmel Studio, ale tak naprawdę to nie kwestia samego Atmel Studio (to tylko IDE - środowisko programistyczne), lecz atmelowskiego toolchaina, który w zasadzie jest oparty na avr-gcc (nie wiem, od której wersji gcc posiada wsparcie dla "named address spaces"). Właściwie toolchain ten można zainstalować i skonfigurować do współpracy z innym środowiskiem programistycznym (np. Eclipse) i używać w nim __flash. Moim zdaniem główną przewagą Atmel Studio nadal jednak będzie dobry symulator.

    Mictronic napisał:
    ...czym grozi uzywanie opcji optymalizacji 3...

    Nie bardzo wiem, czego się obawiasz. -O3 to optymalizacja pod kątem szybkości wykonania, więc w stosunku np. do -Os wzrośnie zapewne rozmiar kodu wynikowego. Prościej mówiąc, przy bardziej rozbudowanym programie może zabraknąć flasha.
    Poczytaj może ten artykuł.
  • #13 14829657
    Konto nie istnieje
    Konto nie istnieje  
  • #14 14829971
    tmf
    VIP Zasłużony dla elektroda
    Posty: 14318
    Pomógł: 2090
    Ocena: 2205
    Mictronic napisał:
    Rzeczywiscie chodzilo mi o atmel studio.
    Dziekuje za ludzkie wyjasnienie problemu. Kod w atmel studio jest na starcie mniejwiecej 2x mniejszy niz w avrgcc pomimo tych samych stopni optymalizacji.


    No to jakaś magia. Bo Atmel Studio jak pisał już przedmówca to tylko IDE, wykorzystujące do kompilacji ten sam kompilator avr-gcc. Być może w innej (nowszej) wersji, lecz różnice w kompilacji sięgające 50% przy tych samych opcjach kompilacji są po prostu niemożliwe.
  • #15 14830475
    Konto nie istnieje
    Konto nie istnieje  
  • #16 14830928
    tmf
    VIP Zasłużony dla elektroda
    Posty: 14318
    Pomógł: 2090
    Ocena: 2205
    -Os to nie jedyna optymalizacja. Przypuszczam, że różnice wynikają z dużej ilości nieużywanych funkcji lub danych. AS kompiluje z opcjami umożliwjącymi ich automatyczne usunięcie, PN prawdopodobnie nie. Zagadka w miarę prosta do rozwiązania, wystarczy wygenerować listę obiektów z ich rozmiarami z pliku elf i porównać.

Podsumowanie tematu

LABEL_AI_GENERATED
Dyskusja dotyczy przekazywania wskaźników do dwuwymiarowych tablic w pamięci PROGMEM w kontekście programowania na platformie AVR. Użytkownicy omawiają problemy związane z odczytem danych z pamięci FLASH oraz różnice w zachowaniu wskaźników do pamięci SRAM i FLASH. Wskazano, że kompilator nie może poprawnie obliczyć adresów elementów tablicy, jeśli nie zna jej wymiarów. Proponowane są różne podejścia, w tym użycie makr do automatycznego przekazywania rozmiarów tablic oraz zastosowanie struktury do przechowywania danych. Użytkownicy dzielą się również doświadczeniami z różnymi środowiskami programistycznymi, takimi jak Atmel Studio i avr-gcc, oraz omawiają wpływ opcji optymalizacji na rozmiar kodu.
Podsumowanie AI na podstawie dyskusji. Może zawierać błędy.
REKLAMA