Elektroda.pl
Elektroda.pl
X
Please add exception to AdBlock for elektroda.pl.
If you watch the ads, you support portal and users.

[LPC2138][C/Keil] - Symulator swoje, MCU swoje (struktury z polami bitowymi)

Electix 13 Dec 2012 16:12 1917 11
  • #1
    Electix
    Level 21  
    Witam serdecznie!

    Natknąłem się na taki oto problem. Napisałem sobie funkcję, która służy do ustawiania rejestru Mach Control Register i wygląda tak:
    Code: c
    Log in, to see the code


    I robię sobie takie wywołanie:
    Code: c
    Log in, to see the code


    I zauważyłem taki problem:

    -Gdy symuluję tą funkcję w symulatorze, to na podglądzie ustawień rejestrów timera0 ustawiane opcje resetu i przerwania dla Mach0 są prawidłowe.
    -Gdy program odpalam na sprzęcie i podglądam rejestry debuggerem, okazuje się, że przedstawiona funkcja oprócz ustawienia wymaganych bitów w rejestrze MCR ustawia jeszcze dodatkowo przerwanie dla Mach3 i reset dla Mach2.

    Czy ktoś z Was, szanowni Koledzy spotkał się już z takim problemem? Albo orientuje się skąd on może wynikać? Czyżby symulator był błędnie napisany? A może używanie struktur z polami bitowymi w mikrokontrolerze wiąże się z nieprzewidywanymi działaniami?
  • #2
    rajszym
    Level 20  
    Pokaż tę funkcję w listingu assemblera.
  • #3
    Electix
    Level 21  
    Wkleiłem sto z listingu ASM, mam nadzieję że będzie w miarę czytelne:
    Code: asm
    Log in, to see the code
  • Helpful post
    #4
    User removed account
    User removed account  
  • #5
    rajszym
    Level 20  
    Kompilacja jest jak najbardziej prawidłowa i tego oczywiście należało się spodziewać.
    Jedna mała uwaga - kompilator generuje kod, który powoduje, że operacje bitowe wykonywane są na bajtach, a nie na słowach 4-bajtowych. Być może jest to powód takiego a nie innego zachowania.
  • #6
    Electix
    Level 21  
    No właśnie zauważyłem, przechodząc krok po kroku, że rzeczywiście operacje są wykonywane na bajtach. Wszystko przebiega identycznie i w symulacji i w MCU, z tą różnicą, że zapis wyniku operacji w rejestrze docelowym powoduje iż w MCU oprócz włączonego bitu 0 rejestru MCR zapala się bit 8. W symulatorze, taka sytuacja nie ma miejsca.

    Czy problem ten może się brać stąd, że rejestr ten powinien być zapisywany wartością 32b? Czy to są jakieś uwarunkowania sprzętowe? Ciężko jest mi zrozumieć ten problem.

    I czy właściwym wnioskiem z tego zdarzenia będzie, żeby pozamieniać wszystkie struktury z polami bitowymi, na zwykłe operacje bitowe?

    A może da się jakoś inaczej rozwiązać ten problem? Nie ukrywam, że kod w którym odnosi się do pól bitowych, jest bardziej czytelny od operacji bitowych. Z porównań co do długości kodu, wyszło mi też, że posługując się strukturami z polami bitowymi, kod jest krótszy...
  • Helpful post
    #7
    rajszym
    Level 20  
    Spróbuj bez __packed przed struct
  • #8
    Electix
    Level 21  
    Podziałało... :)
    Właśnie zacząłem się już zastanawiać, czy wyrównywanie pól struktury, czegoś tu nie miesza. No i wygląda na to że tak. No i w tym przypadku kod podziałał prawidłowo. Tylko czy czasem znów gdzieś nie wyjdą inne krzaki? Zawsze stosowałem __packed żeby nie mieć rozsypki miedzy polami i mieć pewność że poszczególne pola nie są wyrównywane do nibli, bajtów, czy słów. Okazuje się, że chyba do końca nie rozumiałem działania tego kwalifikatora...

    __packed

    Czy jest jeszcze coś, co powinienem wiedzieć na ten temat, albo na co zwrócić uwagę? Piszę soft do mojego dyplomu i nie chce mi się już gdzieś błądzić po drodze szukając takich krzaczków. Może ja za dużo chcę wyciągnąć z tego kompilatora? Bo jak tak przeglądałem sobie różnego rodzaju biblioteki, przykłady programów od NXP i STM, to w ich kodach, nie widziałem żeby ktokolwiek posługiwał się tak jak ja strukturami, wszyscy zasuwali na operacjach bitowych...

    Tak na marginesie, zastanawiam się też, czy zgłosić to do Keila, że w symulatorze wszystko działało poprawnie, a na sprzęcie już nie...

    No i nauczka, nie wierzyć symulatorom na słowo... :P
  • #9
    rajszym
    Level 20  
    Jak widać nie wszyscy. Już jest nas dwóch... :)
  • #10
    Electix
    Level 21  
    Czy ktoś jeszcze chciałby coś dodać w tym temacie? Czy mogę zrobić podsumowanie i go zamknąć? :)
  • #11
    User removed account
    User removed account  
  • #12
    Electix
    Level 21  
    Podsumowanie:

    1. Używając struktur z polami bitowymi w Keil µVision, nie należy używać kwalifikatora __packed, ponieważ powoduje on nadpisywanie "nadprogramowych" bitów w rejestrze.

    2. Symulator w Keilu, nie pokazuje tego błędu, problem ujawnia się dopiero na sprzęcie.

    3. Zawsze warto dokładnie sprawdzić i prześledzić, czy kompilator porozmieszczał pola bitowe zgodnie z naszymi oczekiwaniami.

    4. Jeżeli nie rejestruje się żadnych nieprawidłowości, takich jak wymienione niżej, to uważam że, stosowanie pól bitowych zamiast operacji bitowych na rejestrach, jest bardziej przejrzystą formą programowania. Należy jednak uwzględnić spostrzeżenie:
    Albert wrote:
    Pola bitowe są z natury nieprzenośne. Standard C nie gwarantuje nawet kolejności ich rozmieszczenia.
    Wystarczy więc zmiana kompilatora (przy tym samym MCU) i wszystko może wziąć w łeb.

    Jeżeli komuś zależy na przenośności kodu.

    Temat zamykam :)