Skocz do zawartości

Tablica liderów


Popularna zawartość

Pokazuje zawartość z najwyższą reputacją 21.09.2019 we wszystkich miejscach

  1. 4 punkty
    Co więcej kod wynikowy obu wersji będzie taki sam. Żadnej alokacji pamięci nie będzie, no chyba że ktoś zacznie robić jakieś nieeleganckie sztuczki z tak zadeklarowanymi stalymi, np. odczytując ich adres. W poprawnie napisanym programie nic złego się nie wydarzy, nie będzie też marnowania zasobów.
  2. 2 punkty
    @ethanak Wyszło, że dla jednego pliku działa tak jak reszta się spodziewała, więc "oszukałeś" i rozbiłeś to na oddzielne jednostki kompilacji przez co wymusiłeś żeby ta dana została - to inaczej nie mogło zadziałać - moduły zostały skompilowane tak, żeby tą wartość odczytać - więc tak to finalnie musiało być. Optymalizacja działa w obrębie jednostki kompilacji. Sprawę załatwi link time optimalization - przy "szerszym spojrzeniu" linker zobaczy, że to jest const i inaczej to zrobi - finalnie nie będzie nic w sekcji data. avr-gcc -flto -fdata-sections -ffunction-sections -c -o sc1.o sc1.cpp avr-gcc -flto -fdata-sections -ffunction-sections -c -o sd1.o sd1.cpp avr-gcc -flto -fdata-sections -ffunction-sections -c -o dw.o dw.cpp avr-gcc -flto -Wl,-gc-sections -o s1.elf sc1.o sd1.o dw.o avr-size s1.elf Natomiast fajnie, że constexpr załatwia sprawę - warte zapamiętania. [UPDATE] A nawet trochę za daleko pojechałem - już wsadzenie tego w sekcję, bez - flto powoduje ten sam efekt. Czyli chodziło mniej więcej o to co pisał Elvis wcześniej: "Zapomniałeś o opcji dla linkera - bez niej nieużywane śmieci zostają w pamięci."
  3. 2 punkty
    Cześć, na wszystkich większych forach, mimo szczerych chęci użytkowników, zdarzają się różne niemiłe sytuacje. Większe lub mniejsze zgryźliwości, ogólne odsyłanie do wyszukiwarki itd. Z punktu widzenia nowych czytelników są to sytuacje, które zniechęcają do udzielania się na forum. Często zdarza się też tak, że jakaś osoba chętnie udziela pomocy w 100 tematach, a w jednym miejscu napisze coś mniej miłego i od razu robi się "afera", która psuje atmosferę i reputację danej osoby. Wydaje mi się, że atmosfera panująca na Forbocie jest całkiem dobra, ale chciałbym jednak wprowadzić pewne rozwiązania, które jeszcze ją poprawią. Roboczo nazwałem tę kwestię PPF (Polityką Przyjaznego Forum). Chciałbym wprowadzić kilka zasad, które będą dotyczyły zarówno osób zadających pytania, jak i tych, które odpowiadają. Mam już swój szkic zasad tego typu, ale nie chcę jeszcze go tutaj publikować, bo może ktoś z Was podpowie coś ciekawego (nie chcę niczego sugerować). Dobrym przykładem mogą być wytyczne dostępne na StackExchange (polecam lekturę szczególnie pierwszego linka): https://electronics.stackexchange.com/conduct https://electronics.stackexchange.com/help/how-to-ask Co sądzicie o wprowadzeniu tego typu zasad? Macie jakieś propozycje wytycznych, które warto byłoby wprowadzić? Podkreślam, że chodzi o zasady, które będą dotyczy obu stron: pytających oraz odpowiadających.
  4. 2 punkty
    Zaraz zaraz... Kod pierwszy: extern void digitalWrite(int, int); #define PIN 2 int main(void) { digitalWrite(PIN,1); } Kod drugi: extern void digitalWrite(int, int); const int PIN = 2; int main(void) { digitalWrite(PIN,1); } I teraz: $ avr-gcc -Os -S -o k1.s k1.c $ avr-gcc -Os -S -o k2.s k2.c $ diff k1.s k2.s 1c1 < .file "k1.c" --- > .file "k2.c" 23a24,29 > .global PIN > .section .rodata > .type PIN, @object > .size PIN, 2 > PIN: > .word 2 24a31 > .global __do_copy_data Gdzie to takie same? Co robię źle?
  5. 1 punkt
    Poniższa dyskusja została wydzielona z innego tematu od poniższego miejsca: ----- No - różnica jest, i to wielka. const tworzy zmienną, która nie pozwala do siebie nic wstawić. Możliwy jest odnośnik lub wskaźnik do takiej zmiennej, a zmienna zajmuje ileśtam bajtów w RAM-ie. #define nic nie tworzy, po prostu preprocesor w miejsce symbolu wstawia jego rozwinięcie. Nie ma żadnej zajętości pamięci, ale jeśli rozwinięciem jest literał - nie możemy użyć referencji czy wskaźnika. Czyli: void fun(const int *); const int a = 7; #define b 7 fun(&a); // dobrze fun(&b); // błąd - preprocesor przetworzy to na fun(&7) Osobiście wolę #define czy enum, bo istnieją tylko w czasie kompilacji, a w maciupciej pamięci AVR-a (gdzie każdy bajt się liczy) nie widzę potrzeby zajmowania ani jednego bajtu na jakieś consty. Przy okazji - nieprawidłowe użycie const może doprowadzić do bardzo trudnych do znalezienia błędów. Oto przykład kodu w C/C++ - odpowiedzcie na pytania bez angażowania kompilatora : #include <stdio.h> const int a = 7; void fun(int *x) { *x=11; } int main(void) { fun((int *)&a); printf("%d\n",a); } Czy ten program się skompiluje? Jeśli tak, jaki będzie wynik jego wykonania np. pod Linuksem? Podobny szkic dla Arduino: const int a = 7; void setup(void) { Serial.begin(9600); *(int *)&a = 11; Serial.println(a); } void loop(void) { } Czy program się skompiluje? Jeśli tak, co wypisze
  6. 1 punkt
    Co rozumiesz przez "kompilowane są jednocześnie"? [UPDATE] Nawet teraz widzę, że LTO jest domyślnie uruchomione w arduino - może nie we wszystkich wersjach tak jest.
  7. 1 punkt
    Wcale nie oszukiwałem! Po prostu zawsze staram się trzymać w jednym pliku konkretny fragment kodu. LTO zadziała tylko jeśli wszystkie pliki kompilowane są jednocześnie - builder Arduino IDE kompiluje je oddzielnie, czyli nic nie zmieni.
  8. 1 punkt
    Strzelam: bo autor w programie posługuje się zamiast nazwami pinów NodeMCU (np. D6, co oznacza GPIO12, czyli pin do dyspozycji programisty grzecznie podłączony do nogi oznaczonej D6 na NodeMCU) cyferkami (np. 6, co oznacza GPIO6, który to pin podłączony wyłącznie wewnętrznie odpowiedzialny jest za komunikację z pamięcią flash i próba jakichś operacji na tym pinie powoduje natychmiastowy crash)?
  9. 1 punkt
    Ta dyskusja już dawno nie ma sensu, albo chociaż związku z tematem watku - więc może prośba do moderatora o wydzielanie tej zaciętej dyskusji do oddzielnego tematu? W każdym razie moje podsumowanie jest takie: oryginalny kod działa tak samo z const, jak i z define. Natomiast ogólnie lepiej używać define niż const, a najlepiej constexpr. Chyba że ktoś ma inne zdanie, ja chętnie dowiem się czegoś nowego
  10. 1 punkt
    Marne mam pojęcie o czym piszecie:-/ ;), dyskusja poszła w ciekawym kierunku... jednak jak mniemam autora wątku interesuje rozwiązanie problemu, dlaczego dodanie tych "dziwnych" (dla mnie;)) define blokuje wykonywanie jego programu...
  11. 1 punkt
    Zmieniłem dwie rzeczy w kodzie @ethanak : const na constepr, reszta pozostaje identyczna: //testy1.h: extern void pinOn(void); constexpr int PIN = 7; extern void digitalWrite(int, int); // sc1.cpp #include "testy1.h" // const int PIN = 7; int main(void) { pinOn(); } Budowanie ze wsparciem dla C++11: avr-gcc -std=c++11 -Os -Wl,--gc-sections -mmcu=atmega328p -o s1.elf sc1.cpp sd1.cpp dw.cpp avr-gcc -std=c++11 -Os -Wl,--gc-sections -mmcu=atmega328p -o s2.elf sc2.cpp sd2.cpp dw.cpp avr-size s1.elf text data bss dec hex filename 188 0 0 188 bc s1.elf avr-size s2.elf text data bss dec hex filename 188 0 0 188 bc s2.elf Jak widzimy przy wykorzystaniu constexpr osiągamy ten sam plik wynikowy co przy #define. * dodatkowo, gdy wyrzucimy extern z pliku testy1.h i zadeklarujemy i zdefiniujemy const int PIN = 7; znowu otrzymamy ten sam kod wynikowy co w przypadku użycia #define ale już bez konieczności używania C++11. Dlatego preferowaną metodą definiowania stałych w C++ jest definiowanie i deklarowanie ich w jednym miejscu. Dla ciekawych możliwości nowoczesnego C++ polecam prezentację Jasona Turnera: “Rich Code for Tiny Computers: A Simple Commodore 64 Game in C++17” którą można zobaczyć na youtube.
  12. 1 punkt
    To chyba udało ci się w końcu oszukać kompilator. W sumie to wiara w moc optymalizacji jest ułomna, a jak widać na załączonym obrazku nawet prosty program może przechytrzyć kompilator. A tak z ciekawości - gdyby zamiast const użyć constexpr to kod byłby taki sam w obu przypadkach? Może należy jednak polubić C++11 albo wrócić do stylu C.
  13. 1 punkt
    Nie zauważyłeś, że tu nie ma nieużywanych śmieci. Przy dokładnie takich samych opcjach jak Twoje mam: $ avr-size sg1.elf text data bss dec hex filename 214 2 0 216 d8 sg1.elf $ avr-size sg2.elf text data bss dec hex filename 188 0 0 188 bc sg2.elf
  14. 1 punkt
    Zapomniałeś o opcji dla linkera - bez niej nieużywane śmieci zostają w pamięci.
  15. 1 punkt
    No to troszkę inaczej, czyli bliżej rzeczywistości. Plik dw.cpp identyczny w obu przypadkach: void digitalWrite(int pin, int value) { volatile int a = pin; volatile int b = value; } Zestaw pierwszy: plik sc1.cpp: #include "testy1.h" const int PIN = 7; int main(void) { pinOn(); } plik sd1.cpp: #include "testy1.h" void pinOn(void) { digitalWrite(PIN,1); } plik testy1.h: extern void pinOn(void); extern const int PIN; extern void digitalWrite(int, int); Zestaw drugi: plik sc2.cpp: #include "testy2.h" int main(void) { pinOn(); } plik sd2.cpp: #include "testy2.h" void pinOn(void) { digitalWrite(PIN,1); } plik testy2.h: extern void pinOn(void); #define PIN 7 extern void digitalWrite(int, int); I teraz kompilacja: $ avr-gcc -Os -o s1.elf sc1.cpp sd1.cpp dw.cpp $ avr-gcc -Os -o s2.elf sc2.cpp sd2.cpp dw.cpp $ avr-size s1.elf text data bss dec hex filename 80 2 0 82 52 s1.elf $ avr-size s2.elf text data bss dec hex filename 52 0 0 52 34 s2.elf Jak widać, w przypadku const kod jest dłuższy, a w sekcji data mamy naszego pina Przypadek ze static pominąłem.
  16. 1 punkt
    Proponuję przeprowadzić następujący test: Po pierwsze należy porównywać programy wynikowe, a nie efekty pośrednie działania kompilatora. Wobec tego przykłady należy trochę zmienić - żeby się kompilowały i nie były puste: test1.c void digitalWrite(int a, int b) { volatile int xa = a; volatile int xb = b; } #define PIN 2 int main(void) { digitalWrite(PIN,1); } test2.c void digitalWrite(int a, int b) { volatile int xa = a; volatile int xb = b; } const int PIN = 2; int main(void) { digitalWrite(PIN,1); } Kompilacja: avr-gcc -Os -c test1.c avr-gcc -Os -c test2.c avr-gcc -Os -Wl,--gc-sections -mmcu=atmega328p -o test1.elf test1.o avr-gcc -Os -Wl,--gc-sections -mmcu=atmega328p -o test2.elf test2.o Teraz można porównać co wyszło: elvis@raider:~/blink_test/test$ avr-size test1.elf text data bss dec hex filename 178 0 0 178 b2 test1.elf elvis@raider:~/blink_test/test$ avr-size test2.elf text data bss dec hex filename 200 0 0 200 c8 test2.elf Jak widać po danych nie ma nawet śladu, ani w segmencie data, ani bss. Co ciekawe wersja z const daje większy plik wynikowy - ale to już taki urok kompilatora Można zawsze wygnerować faktycznie użyte pliki i popatrzeć czym się różnią: elvis@raider:~/blink_test/test$ avr-objdump -d test1.elf > test1.s elvis@raider:~/blink_test/test$ avr-objdump -d test2.elf > test2.s Po stałej PIN w obu przypadkach nie ma śladu, natomiast faktycznie kompilator trochę gorzej się zachował po zobaczeniu const. W każdym razie używanie const nie powoduje zużycia pamięci RAM, ta zmienna, która była widoczna w plikach .o jest usuwana przez linker, bo nie jest do niczego potrzebna.
  17. 1 punkt
    Sprawdziłeś zawartość plików wynikowych jak napisałem wcześniej, czy ciągle porównujesz tylko pliki .o ?
  18. 1 punkt
    No ale to już jest naciąganie - sztuczne tworzenie zmiennych statycznych. Jeśli program składa się z więcej niż jednego pliku (co jest raczej normalne przy czymś poważniejszym niż "Hello world") tworzenie identycznych statycznych zmiennych nie jest raczej dobrą praktyką. Owszem - można w jakimś pliku "cośtam.h" zdefiniować "static const int cośtam = ileśtam" i inkludować go gdzie się da - ale czy nie jest to po prostu próba ominięcia #define (które w pojęciu zatwardziałych cdwuplosowców jest be i fujaste i powinno wylecieć z języka)?
  19. 1 punkt
    @Matthew11 możesz porównać wyniowy kod progamu, a nie to co wychodzi po kompilacji samych plików? Bo u mnie linker wyrzuca nieużywaną sekcję, więc pliki .o mają dodatkowy bagaż, ale docelowy elf już nie. Dodatkowy test dla ciekawskich - dodanie static do const. Wtedy każdy kompilator powinien już dać poprawny wynik, nawet w plikach pośrednich. Edit: Coś co mnie dla odmiany zaciekawiło - użycie avr-g++ zamiast avr-gcc daje inny kod i wtedy oba pliki są identyczne nawet na etapie plików obiektowych... Może dlatego tylko entuzjaści C++ lubią wersję z const
  20. 1 punkt
    Okej, w przypadku C @ethanak ma rację - const daje nam dodatkowy bagaż. Ale w przypadku gdy nasz kod jest w C++: avr-gcc -Os -S -o k1.s k1.cpp avr-gcc -Os -S -o k2.s k2.cpp diff k1.s k2.s 1c1 < .file "k1.cpp" --- > .file "k2.cpp" * sprawdzone na $avr-gcc -v -> gcc version 5.4.0 (GCC) ** https://godbolt.org/ kompiluje .cpp - dlatego wynikowy assembler był taki sam
  21. 1 punkt
    Przetestowałem z Arduino 1.8.9 i kod jest identyczny. Więc pewnie sporo zależy od wersji kompilatora użytych ustawień itd. No i wypadałoby chyba porównywać kod programu, a nie coś pośredniego. W każdym razie kod z const jest bardzo łatwo popsuć, dlatego dawno temu polecano używanie #define. Obecnie moda się zmieniła i fanatycy C++ preferują const. Od czasów C++11 dostępny jest operator constexpr, który działa z moją wersją Arduino - może to pogodzi obie strony?
  22. 1 punkt
  23. 1 punkt
    Sam tytuł mówi prawie wszystko na temat tej zabawki. Co do genezy to od jakiegoś czasu miałem chęć zrobić pada opartego o arduino. Sam pad nie miał służyć do grania a bardziej do sterowania czymś innym. Całość najpierw powstała w SimulIDE Tak jak widać do każdego przycisku są przypisane diody czyli 4 po lewej jedna po prawej (plus led na pinie13) i cztery diody sygnalizacyjne na środku. Po dostarczeniu zasilania diody zaświecają się jedna po drugiej a naszym celem jest wcisnąć odpowiadający danej diodzie przycisk co powoduje jej zgaszenie. Jeśli nie wciśniemy przycisku lub wciśniemy go po czasie zapala się dioda sygnalizacyjna. Możemy pominąć trzy diody a przy czwartej jest game over . W raz z postępem rozgrywki diody gasną i zapalają się coraz szybciej. Cel był taki żeby rozgrywka była możliwie krótka a stopień trudności narastał dając nam odczuć wyraźną zmianę. tak wygląda efekt końcowy. Chciałem kupić diody w kształcie kwadrat 12x12mm ale nie było ich w sklepie więc trudno. Za brakujące elementy zapłaciłem 7 zł resztę miałem. W załączniku przesyłam plik do simulIDE wraz z kodem (całym). Można skompilować i wgrać bezpośrednio z simulIDE i zobaczyć jak to działa w symulacji. void setup() { Serial.begin(9600); DDRC = 15; // A0..A3 Output DDRB = 48; //D8...D11 INPUT, D12 and D13 Output PORTB = 15; //D8...D11 High impedance DDRD = 60; //D2...D5 OUTPUT PORTD = 192; //D6 D7 High impedance PCICR = 5; // enable pin change interrupt bank 0 and 2 PCMSK0 = 15; //enable pin change interrupt PCINT0...PCINT3/D8...D11 PCMSK2 =192; // enable pin change interrupt D6 D7 } void loop() { start(randomPin,ledOn,ledOff); } ISR(PCINT0_vect) { for (byte i=0; i<4; i++) { if (bitRead(PINB,i)==0 && bitRead(PIND,2+i)==1) {score++; bitClear(PORTD, 2+i);} } } ISR(PCINT2_vect) { for (byte i=0; i<2; i++) { if (bitRead(PIND,i+6)==0 && bitRead(PINB,i+4)==1) {score++; bitClear(PORTB,i+4);} } } Polecam zrobienie podglądu w rejestry (jeśli ktoś wcześniej tego nie robił) z poziomu simulIDE naprawdę bardzo przydatna sprawa. I to by było na tyle. A co do samego refleksu to udało mi się zgasić ponad 100 diod. Pin_interruptPad.zip
  24. 1 punkt
    Sprawdziłem cały kod i jeśli wywalę ten z const to działa. Czy mogę const usunąć i INT zostawić ? Nie rozsypie się coś?
  25. 1 punkt
    Co możemy szybko i łatwo sprawdzić porównując wynikowy assembler obu wersji: https://godbolt.org/z/AzPxGk który dla obu wersji jest identyczny pod AVR gcc 5.4.0 (różni się jedynie wartością, którą reprezentuje `PIN` w celu odróżnienia wersji).
  26. 1 punkt
  27. 1 punkt
    Możesz jeszcze spróbować zmniejszyć w programie prędkość I2C.
  28. 1 punkt
    W takim razie doprecyzuje, że w przypadku wykorzystywania const do deklaracji pinu (a tutaj mowa była o takim przypadku) nie będzie to robiło różnicy od strony praktycznej. Obie wersje zadziałają.
  29. 1 punkt
    Wszystko zależy od tego co to za projekt. Czy ma działać tylko chwilę czy to coś, co będzie pracowało przez kilka lat, a jego działanie jest "krytyczne". Jeśli to nie problem to warto przetestować rozwiązania w kolejności od najprostszych, czyli: rezystory, wymiana kabla, a jak to nie pomoże to dopiero wtedy szedłbym w jakieś bardziej rozbudowane rozwiązania
  30. 1 punkt
    @SOYER tak też można, to nic złego Jest wiele metod, nie powinno to wpływać na działanie programu. Więcej na ten temat znajdziesz tutaj: https://www.arduino.cc/reference/en/language/variables/variable-scope--qualifiers/const/
  31. 1 punkt
    @espiridion ten interfejs nie jest raczej dedykowany do komunikacji na dalekie odległości, ale jest szansa, że zadziała. Wiele zależy od samego przewodu oraz warunków w jakich wykonujesz te testy (kwestia zakłóceń). Zerknij na ten artykuł: https://hackaday.com/2017/02/08/taking-the-leap-off-board-an-introduction-to-i2c-over-long-wires/
Tablica liderów jest ustawiona na Warszawa/GMT+02:00
×
×
  • Utwórz nowe...