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

[Rozwiązano] [ATMEL AVR][C/AS7] - konwersja typu uint8_t na uint16_t przy negacji logicznej

JarekC 18 Sty 2020 17:13 453 5
  • #1 18411311
    JarekC
    Poziom 32  
    Witam,
    Ponieważ postanowiłem spróbować jak sprawuje się programetr/debugger MPLAB SNAP to przesiadłem się IAR Embedded Workbench (darmowa wersja 4kB) na Atmel Studio 7 które obsługuje SNAPa.

    Po lekkich problemach z pierwszym podłączeniem działa bardzo fajnie.

    Ale pojawiły się problemy z działaniem kodu napisanego w C.
    Poniżej fragment programu i wygenerowany kod (dissasemblacja) dla 1 poziomu optymalizacji.

    Ogólne założenia iż w buforze znajdują się dwa znaki (odebrane z UARTA) przy czym
    aby warunek był spełniony pierwszy znak musi być z zakresu 0x00-0x0F a drugi znak musi być jego negacją bitową, np 0x0F i 0xF0
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    O ile pierwszy warunek jest sprawdzany 8-bitowo:
    -dana z bufora do R24
    -wydzielenie starszych bitów
    -sprawdzenie czy wynik to 0
    i tu wszystko jesk OK

    Ale drugi warunek jest sprawdzany 16-bitowo
    - pierwsza dana z bufora do R18 plus wyzerowanie R19 (para R19:R18)
    - druga dana z bufora do R24 plus wyzerowanie R25 (para R25:R24)
    - zanegowanie R25:R24
    - porównanie 16-bitowe
    - sprawdzenie warunku.

    Tylko to nie zadziała poprawnie
    Dla przykładu receiveBuffer[2]=0x00, receiveBuffer[3]=0xFF
    czyli warunek powinien być spełniony.

    A w programie będzie
    R19:R18 = 0x0000
    R25:R24 = 0x00FF, negacja R25:R24 = 0xFF00
    więc warunek nie będzie spełniony.

    Kod: AVR assembler
    Zaloguj się, aby zobaczyć kod


    Po kilku różnych podejściach typu
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
    to działa poprawnie
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
    to nie działa poprawnie

    Doszedłem do tego że w przypadku zastosowania operatora negacji bitowej ~ następuje rozszerzenie typu na 16 bitowy i dopiero ponowne rzutowanie na uint8_t daje poprawny rezultat.

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
    to działa poprawnie

    Z ciekawości wróciłem do IARa i sytuacja jest podobna (tam od razu warunek uznawany jest za niespełniony i kod optymalizowany) więc jest to prawidłowe działanie.

    I jak zawsze wyszło że to nie błąd kompilatora tylko programisty ale pytanie od elektronika a nie programisty dlaczego następuje konwersja typu?

    Przy pobieżnym przeglądnięciu info na temat operatorów logicznych nie znalazłem takiej uwagi.
    Piszę o tym bo może ktoś inny również trafi na taki problem.

    Pozdrawiam
    JarekC
  • #2 18411351
    excray
    Poziom 41  
    JarekC napisał:
    a drugi znak musi być jego negacją bitową, np 0x0F i 0xF0

    if((receiveBuffer[2] ^ receiveBuffer[3])==0xFF)...
  • Pomocny post
    #4 18411533
    Konto nie istnieje
    Poziom 1  
  • #5 18411595
    JarekC
    Poziom 32  
    Ok.
    Tak wiem że uint8_t to typedef dla unsigned char.

    Teraz załapałem czyli gdy nie ma jawnego lub niejawnego rzutowania na unsigned char to zmienna po operacji staje się int.
    Sprawdziłem dla innego przypadku
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    też następuje "integer promotion"

    Dzięki.
  • #6 18411599
    JarekC
    Poziom 32  
    Ok.
    Tak wiem że uint8_t to typedef dla unsigned char.

    Teraz załapałem czyli gdy nie ma jawnego lub niejawnego rzutowania na unsigned char to zmienna po operacji staje się int.
    Sprawdziłem dla innego przypadku
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    też następuje "integer promotion"

    Dzięki.

    Dodano po 1 [minuty]:

    Temat zamykam, jak opisano we wcześniejszych postach chodziło o "integer promotion".
REKLAMA