eGospodarka.pl

eGospodarka.plGrupypl.misc.elektronika › Zagwozdka w C Keil.
Ilość wypowiedzi w tym wątku: 84

  • 1. Data: 2019-02-10 22:32:33
    Temat: Zagwozdka w C Keil.
    Od: "Irek.N." <t...@j...taki.jest.pl>

    Pytanie do znawców C. Czy zapis taki:

    volatile unsigned int DEL_STEP;

    void DELAY(unsigned int Czas)
    {
    DEL_STEP = Czas;
    while(DEL_STEP);
    }

    może różnić się wykonaniem od zapisu takiego?

    void DELAY(unsigned int Czas)
    {
    unsigned char DEL_MSB,DEL_LSB;
    DEL_STEP = Czas;
    while(1)
    {
    DEL_LSB = DEL_STEP/0x100;
    DEL_MSB = DEL_STEP^0x100;
    if(DEL_MSB == 0 & DEL_LSB == 0)
    return;
    }
    }

    Znalazłem błąd w starym kodzie. Ze zdziwieniem odkryłem, że w komendzie
    while(DEL_STEP); kompilator sprawdza tylko LSB zmiennej. Oczywiście
    generuje to kłopoty, gdy DEL_STEP przekracza wartość 255.
    Przepisanie jak niżej rozwiązuje problem, ale nie kumam powodu jego
    wystąpienia. Sprawdziłem optymalizacje, to nie to, po prostu kod jest
    generowany źle. Ktoś ma pomysł dlaczego kompilator uprościł, a może ja
    czegoś nie zauważam?

    Miłego.
    Irek.N.
    ps. DEL_STEP jest modyfikowana w przerwaniu, inaczej procedura nie miała
    by sensu.



  • 2. Data: 2019-02-10 23:01:22
    Temat: Re: Zagwozdka w C Keil.
    Od: Zbych <a...@o...pl>

    Irek.N. wrote on 10.02.2019 22:32:
    > Pytanie do znawców C. Czy zapis taki:
    >
    > volatile unsigned int DEL_STEP;
    >
    > void DELAY(unsigned int Czas)
    > {
    > DEL_STEP = Czas;
    > while(DEL_STEP);
    > }
    >
    > może różnić się wykonaniem od zapisu takiego?
    >
    > void DELAY(unsigned int Czas)
    > {
    > unsigned char DEL_MSB,DEL_LSB;
    > DEL_STEP = Czas;
    > while(1)
    > {
    > DEL_LSB = DEL_STEP/0x100;
    > DEL_MSB = DEL_STEP^0x100;
    > if(DEL_MSB == 0 & DEL_LSB == 0)
    > return;
    > }
    > }
    >
    > Znalazłem błąd w starym kodzie. Ze zdziwieniem odkryłem, że w komendzie
    > while(DEL_STEP); kompilator sprawdza tylko LSB zmiennej.

    Pokaż cały kod wynikowy funkcji DELAY. Oczywiście kompilator może mieć
    błąd, ale dużo bardziej prawdopodobne jest że coś źle interpretujesz.


  • 3. Data: 2019-02-10 23:41:57
    Temat: Re: Zagwozdka w C Keil.
    Od: Mateusz Viste <m...@n...pamietam>

    On Sun, 10 Feb 2019 22:32:33 +0100, Irek.N. wrote:
    > Pytanie do znawców C. Czy zapis taki:
    >
    > volatile unsigned int DEL_STEP;
    >
    > void DELAY(unsigned int Czas) {
    > DEL_STEP = Czas;
    > while(DEL_STEP);
    > }
    >
    > może różnić się wykonaniem od zapisu takiego?
    >
    > void DELAY(unsigned int Czas) {
    > unsigned char DEL_MSB,DEL_LSB;
    > DEL_STEP = Czas;
    > while(1) {
    > DEL_LSB = DEL_STEP/0x100;
    > DEL_MSB = DEL_STEP^0x100;
    > if (DEL_MSB == 0 & DEL_LSB == 0) return;
    > }
    > }

    O "Keil" nigdy nie słyszałem, ale C obiło mi się już o uszy, wrzucę moje
    3 grosze, być może jakkolwiek pomocne :)

    Pierwszy wariant wydaje się bardzo sensowny. Kompilator zepsuty? A może
    typ int nie jest atomiczny, i kompilator sprawdza najpierw jednego nibbla,
    i dopiero jeśli ten okaże się zerowy to zajmie się drugim?
    Próbowałeś może zastąpić jakimś sig_atomic_t?

    Ten drugi przykład to w ogóle lichy jest, bo pętla ma teoretyczne prawo
    zostać przerwana za każdym razem kiedy wartość DEL_STEP zostaje zmieniona
    z wartości o zerowym MSB do wartości o zerowym LSB (np. 0x0034 -> 0x1200)
    - a to dlatego, że los może złośliwie zechcieć wykonać twoje przerwanie
    akurat pomiędzy liniami:

    DEL_LSB = DEL_STEP/0x100;
    DEL_MSB = DEL_STEP^0x100;

    Nazewnictwo jest tu nieco pomieszane, bo DEL_LSB będzie faktycznie
    zawierał 8 "ważniejszych" bitów, tj. MSB. A DEL_MSB będzie zawierał 8
    "mniej ważnych" bitów - z resztą celowość operacji XOR całkiem mi tu
    umyka, tym bardziej że operuje na bitach których DEL_MSB i tak nie
    zobaczy (bo jest charem). Może zamiast '^' (xor) miałeś na myśli
    '%' (mod)? Też byłoby niepotrzebnie, ale byłbym wtedy w stanie zrozumieć
    co autor miał na myśli.

    Swoją drogą, trochę dziwnie patrzeć na dzielenie w takiej operacji. Jeśli
    kompilator mądry, to zoptymalizuje twoje "/ 0x100" do ">> 8", ale jeśli
    na to nie wpadnie... to będzie mało ekologicznie.

    Mateusz


  • 4. Data: 2019-02-10 23:49:06
    Temat: Re: Zagwozdka w C Keil.
    Od: "J.F." <j...@p...onet.pl>

    Dnia Sun, 10 Feb 2019 22:32:33 +0100, Irek.N. napisał(a):
    > Pytanie do znawców C. Czy zapis taki:
    > volatile unsigned int DEL_STEP;
    >
    > void DELAY(unsigned int Czas)
    > {
    > DEL_STEP = Czas;
    > while(DEL_STEP);
    > }
    >
    > może różnić się wykonaniem od zapisu takiego?

    > Znalazłem błąd w starym kodzie. Ze zdziwieniem odkryłem, że w komendzie
    > while(DEL_STEP); kompilator sprawdza tylko LSB zmiennej. Oczywiście
    > generuje to kłopoty, gdy DEL_STEP przekracza wartość 255.
    > Przepisanie jak niżej rozwiązuje problem, ale nie kumam powodu jego
    > wystąpienia. Sprawdziłem optymalizacje, to nie to, po prostu kod jest
    > generowany źle. Ktoś ma pomysł dlaczego kompilator uprościł, a może ja
    > czegoś nie zauważam?

    A moze na tym procesorze int jest 8-bitowy ?

    J.


  • 5. Data: 2019-02-10 23:55:44
    Temat: Re: Zagwozdka w C Keil.
    Od: "J.F." <j...@p...onet.pl>

    Dnia Sun, 10 Feb 2019 22:32:33 +0100, Irek.N. napisał(a):
    > Pytanie do znawców C. Czy zapis taki:

    > volatile unsigned int DEL_STEP;
    >
    > void DELAY(unsigned int Czas)
    > {
    > DEL_STEP = Czas;
    > while(DEL_STEP);
    > }
    >

    > Znalazłem błąd w starym kodzie. Ze zdziwieniem odkryłem, że w komendzie
    > while(DEL_STEP); kompilator sprawdza tylko LSB zmiennej.

    ewentualnie ... kompilator potraktowal to jako wartosc logiczna, i
    uznal ze mu LSB wystarczy, albo wrecz ma niejawny typ logiczny,
    8-bit, dokonal konwersji i sprawdzenia ... i mu sie MSB zoptymalzowal.

    Sprobuj
    while(DEL_STEP != 0);

    J.


  • 6. Data: 2019-02-10 23:59:17
    Temat: Re: Zagwozdka w C Keil.
    Od: "Grzegorz Niemirowski" <g...@p...onet.pl>

    J.F. <j...@p...onet.pl> napisał(a):
    > A moze na tym procesorze int jest 8-bitowy ?
    > J.

    int musi mieć conajmniej 16 bitów, nawet na 8-bitowcu. Natomiast nie musi
    być obsługiwany atomowo.

    --
    Grzegorz Niemirowski
    https://www.grzegorz.net/


  • 7. Data: 2019-02-11 00:10:40
    Temat: Re: Zagwozdka w C Keil.
    Od: "Grzegorz Niemirowski" <g...@p...onet.pl>

    Irek.N. <t...@j...taki.jest.pl> napisał(a):
    > Pytanie do znawców C. Czy zapis taki:
    > volatile unsigned int DEL_STEP;
    > void DELAY(unsigned int Czas) {
    > DEL_STEP = Czas;
    > while(DEL_STEP);
    > }
    > może różnić się wykonaniem od zapisu takiego?
    > void DELAY(unsigned int Czas) {
    > unsigned char DEL_MSB,DEL_LSB;
    > DEL_STEP = Czas;
    > while(1)
    > {
    > DEL_LSB = DEL_STEP/0x100;
    > DEL_MSB = DEL_STEP^0x100;
    > if(DEL_MSB == 0 & DEL_LSB == 0)
    > return;
    > }
    > }
    > Znalazłem błąd w starym kodzie. Ze zdziwieniem odkryłem, że w komendzie
    > while(DEL_STEP); kompilator sprawdza tylko LSB zmiennej. Oczywiście
    > generuje to kłopoty, gdy DEL_STEP przekracza wartość 255.
    > Przepisanie jak niżej rozwiązuje problem, ale nie kumam powodu jego
    > wystąpienia. Sprawdziłem optymalizacje, to nie to, po prostu kod jest
    > generowany źle. Ktoś ma pomysł dlaczego kompilator uprościł, a może ja
    > czegoś nie zauważam?
    > Miłego.
    > Irek.N.
    > ps. DEL_STEP jest modyfikowana w przerwaniu, inaczej procedura nie miała
    > by sensu.

    LSB to least significant bit. Wątpię aby sprawdzany był najmniej znaczący
    bit, może chodziło o bajt. Szkoda, że nie ma kodu asemblerowego. W każdy
    razie to też wątpliwe, raczej sprawdzane jest wszystko, tylko pewnie nie
    naraz. Jeśli procesor jest 8-bitowy, to int ma 16 bitów i obsługiwany jest
    po bajcie a nie atomowo. Czyli de facto są dwa testy, dla młodszego i
    starszego bajtu. Jeśli przerwanie nastąpi między testami to mamy problem.
    Np. jeśli mamy wartość 256, to test młodszego bajtu da 0. Następnie
    przerwanie zmieni wartość na 255. Wówczas wykonany zostanie test starszego
    bajtu i też da zero. A więc zostanie uznane, że cała zmienna ma wartość
    zero, skoro testy obu bajtów wykazały zera. W takich sytuacjach stosuje się
    sekcje krytyczne.

    --
    Grzegorz Niemirowski
    https://www.grzegorz.net/


  • 8. Data: 2019-02-11 00:11:08
    Temat: Re: Zagwozdka w C Keil.
    Od: "Irek.N." <t...@j...taki.jest.pl>

    > Pierwszy wariant wydaje się bardzo sensowny. Kompilator zepsuty? A może
    > typ int nie jest atomiczny, i kompilator sprawdza najpierw jednego nibbla,
    > i dopiero jeśli ten okaże się zerowy to zajmie się drugim?
    > Próbowałeś może zastąpić jakimś sig_atomic_t?

    Nie, na razie nic nie próbowałem.

    > Ten drugi przykład to w ogóle lichy jest, bo pętla ma teoretyczne prawo
    > zostać przerwana za każdym razem kiedy wartość DEL_STEP zostaje zmieniona
    > z wartości o zerowym MSB do wartości o zerowym LSB (np. 0x0034 -> 0x1200)
    > - a to dlatego, że los może złośliwie zechcieć wykonać twoje przerwanie
    > akurat pomiędzy liniami:
    >
    > DEL_LSB = DEL_STEP/0x100;
    > DEL_MSB = DEL_STEP^0x100;

    To prawda, ale przynajmniej pozwoliło mi potwierdzić przyczynę problemów.
    W ogóle kiepsko to przepisałem, znaczek modulo mi się omsknął i jak sam
    zauważyłeś - zamieniłem połówki. Sorki. Zamysł był taki jak podejrzewałeś.

    > Swoją drogą, trochę dziwnie patrzeć na dzielenie w takiej operacji. Jeśli
    > kompilator mądry, to zoptymalizuje twoje "/ 0x100" do ">> 8", ale jeśli
    > na to nie wpadnie... to będzie mało ekologicznie.

    Radzi sobie z takimi zapisami sensownie.

    THX, postaram się wrzucić jak tylko będę mógł kod wynikowy tego fragmentu.

    Miłego.
    Irek.N.


  • 9. Data: 2019-02-11 00:14:55
    Temat: Re: Zagwozdka w C Keil.
    Od: "Irek.N." <t...@j...taki.jest.pl>

    J.F. pisze:
    > Dnia Sun, 10 Feb 2019 22:32:33 +0100, Irek.N. napisał(a):
    >> Pytanie do znawców C. Czy zapis taki:
    >
    >> volatile unsigned int DEL_STEP;
    >>
    >> void DELAY(unsigned int Czas)
    >> {
    >> DEL_STEP = Czas;
    >> while(DEL_STEP);
    >> }
    >>
    >
    >> Znalazłem błąd w starym kodzie. Ze zdziwieniem odkryłem, że w komendzie
    >> while(DEL_STEP); kompilator sprawdza tylko LSB zmiennej.
    >
    > ewentualnie ... kompilator potraktowal to jako wartosc logiczna, i
    > uznal ze mu LSB wystarczy, albo wrecz ma niejawny typ logiczny,
    > 8-bit, dokonal konwersji i sprawdzenia ... i mu sie MSB zoptymalzowal.
    >
    > Sprobuj
    > while(DEL_STEP != 0);
    >
    > J.


    Sorki, źle napisałem na grupie podział na połówki, jak Mateusz zauważył.
    Powinno być:

    DEL_MSB = DEL_STEP/0x100;
    DEL_LSB = DEL_STEP%0x100;

    Choć intencja jest oczywista i niczego to raczej nie zmienia, wypada
    poprawić.

    Sprawdzę Twoją propozycję jutro. Może naprowadzi nas na powód.

    Miłego.
    Irek.N.


  • 10. Data: 2019-02-11 00:28:20
    Temat: Re: Zagwozdka w C Keil.
    Od: "Irek.N." <t...@j...taki.jest.pl>

    > LSB to least significant bit.

    Tak nazwane są zmienne i może niefortunnie napisałem LSB.

    Wątpię aby sprawdzany był najmniej
    > znaczący bit, może chodziło o bajt.

    Sprawdzana jest zmienna DEL_STEP ale tylko w zakresie 8 mniej znaczących
    bitów.

    > Szkoda, że nie ma kodu asemblerowego.
    Postaram się jutro podać.

    > W każdy razie to też wątpliwe, raczej sprawdzane jest
    > wszystko, tylko pewnie nie naraz. Jeśli procesor jest 8-bitowy, to int
    > ma 16 bitów i obsługiwany jest po bajcie a nie atomowo. Czyli de facto
    > są dwa testy, dla młodszego i starszego bajtu. Jeśli przerwanie nastąpi
    > między testami to mamy problem. Np. jeśli mamy wartość 256, to test
    > młodszego bajtu da 0. Następnie przerwanie zmieni wartość na 255.
    > Wówczas wykonany zostanie test starszego bajtu i też da zero. A więc
    > zostanie uznane, że cała zmienna ma wartość zero, skoro testy obu bajtów
    > wykazały zera. W takich sytuacjach stosuje się sekcje krytyczne.

    Zgoda, Mateusz też to zauważył. Ale to nie jest istotne w tym przypadku.
    Warunek jest sprawdzany poza przerwaniami, a zmienna jest modyfikowana w
    przerwaniu. Zastanawiam się, czy może to mieć jakikolwiek znaczenie.
    Może należało by sprawdzić najpierw jedną połówkę, później drugą i
    ponownie pierwszą, dla pewności.

    Miłego.
    Irek.N.

strony : [ 1 ] . 2 ... 9



Szukaj w grupach

Szukaj w grupach

Eksperci egospodarka.pl

1 1 1

Wpisz nazwę miasta, dla którego chcesz znaleźć jednostkę ZUS.

Wzory dokumentów

Bezpłatne wzory dokumentów i formularzy.
Wyszukaj i pobierz za darmo: