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

[STM32F405] STM32F405 - Jak uzyskać opóźnienia 1-3 us i kilkadziesiąt ns przy 21MHz?

dziechu 27 Sty 2015 16:03 1611 25
  • #1 14373776
    dziechu
    Poziom 27  
    Posty: 1609
    Pomógł: 27
    Ocena: 69
    Potrzebuję opóźnień rzędu 1-3 us, czasem kilkadziesiąt ns. Procesor taktowany jest 21MHz. Timer odpada, bo samo kasowanie flagi, ładowanie rejestru licznika i sprawdzanie w pętli flagi trwa zbyt długo. Używam pustego rozkazu NOP, ale nie wiem ile cykli zegarowych on trwa. Poza tym - czy asm("NOP"); nie jest pomijane przy optymalizacji?
  • #2 14373863
    Konto nie istnieje
    Konto nie istnieje  
  • #3 14373869
    dziechu
    Poziom 27  
    Posty: 1609
    Pomógł: 27
    Ocena: 69
    Czy nie można w C jakoś wyłączyć z optymalizacji poszczególne instrukcje lub całe funkcje? Tak jak volatile dla zmiennych?

    Dodano po 2 [minuty]:

    zxelwro800 napisał:
    21MHz = 4,76ns

    To dotyczy NOP?

    zxelwro800 napisał:
    #include delay.h
    _delay_ns(double ns)
    _delay_us(double us)

    Ale chyba samo wywołanie jakiejś funkcji bibliotecznej będzie trwało dłużej.
  • #4 14373908
    Konto nie istnieje
    Konto nie istnieje  
  • Pomocny post
    #5 14373909
    szczywronek
    Poziom 28  
    Posty: 678
    Pomógł: 142
    Ocena: 217
    Wyłączenie optymalizacji to będzie raczej ficzer kompilatora, nie języka. W GCC jest jakiś atrybut, który pozwala zdefiniować poziom optymalizacji dla konkretnej funkcji - coś w stylu
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Co do "nop" to nie ma tak różowo:

    PM0214 napisał:
    NOP does nothing. NOP is not necessarily a time-consuming NOP. The processor might
    remove it from the pipeline before it reaches the execution stage.


    The Definitive Guide to Cortex... napisał:
    Please note that in general the delay created by NOP instruction is not guaranteed, and can vary between different systems (e.g., memory wait states, processor type). If the timing delay needs to be accurate, a hardware timer should be used.
  • #7 14374073
    BlueDraco
    Specjalista - Mikrokontrolery
    Posty: 6479
    Pomógł: 939
    Ocena: 421
    Pseudofunkcja __NOP() działa zgodnie z oczekiwaniami, w zasadzie wykonuje się jeden cykl, ale w przypadku Cortex-M są "efekty wyższego rzędu", które jednak przy 21 MHz i ustawieniu 0WS dla Flash nie powinny występować.
  • #8 14374256
    dziechu
    Poziom 27  
    Posty: 1609
    Pomógł: 27
    Ocena: 69
    Ze względu na zasilanie bateryjne oraz wyświetlacz TFT, zegar jest przełączany. Przy operacjach z TFT jest włączane max 168MHz, przy obsłudze zewnętrznych peryferiów i obliczeniach - 21MHz, pozostały czas kiedy nic nie robi - 4MHz. Flash ma ustawione cykle oczekiwania ze względu na 168MHz, musiałbym to zmieniać przy niższych częstotliwościach. Te krótkie opóźnienia potrzebne mi są do obsługi zewnętrznego ADC. On nie ma sygnałów typu EOC (End Of Conversion), a więc po starcie konwersji trzeba czekać 3us, bo tyle ona trwa. Dlatego muszę jakoś takie opóźnienie uzyskać.
  • #9 14374302
    BlueDraco
    Specjalista - Mikrokontrolery
    Posty: 6479
    Pomógł: 939
    Ocena: 421
    A jak często wykonujesz tę konwersję? Na ogół robi się to synchronicznie przy użyciu timera, wtedy problem oczekiwania na przetwornik odpada. Zwykle nie musisz czytać wyniku natychmiast po konwersji - wystarczy zrobić to przed następną.
  • #10 14374321
    Konto nie istnieje
    Poziom 1  
  • #11 14374454
    dziechu
    Poziom 27  
    Posty: 1609
    Pomógł: 27
    Ocena: 69
    BlueDraco napisał:
    A jak często wykonujesz tę konwersję?

    Konwersja jest dokonywana jednorazowo po naciśnięciu przycisku. Wystawiany jest sygnał startu konwersji i po 3us powinien nastąpić odczyt AD.
  • Pomocny post
    #12 14374508
    BlueDraco
    Specjalista - Mikrokontrolery
    Posty: 6479
    Pomógł: 939
    Ocena: 421
    To co za różnica, kiedy odczytasz wynik? Przecież to kompletnie nieważne, czy poczekasz 3us, czy 10 ms. Generujesz sztuczne problemy.
  • #14 14374698
    dziechu
    Poziom 27  
    Posty: 1609
    Pomógł: 27
    Ocena: 69
    BlueDraco napisał:
    To co za różnica, kiedy odczytasz wynik?

    Jest różnica. ADC odczytuje 256 pikseli linijki CMOS, odczytuje 13 razy więc razem jest 3328 odczytów ADC. Całość musi być odświeżana w miarę często, tak długo, jak długo trzymany jest przycisk.

    Dodano po 5 [minuty]:

    BlueDraco napisał:
    Na ogół robi się to synchronicznie przy użyciu timera

    Nie bardzo rozumiem synchronicznie z czym. Co przerwanie może zmienić? Może wywołać procedurę odczytu ADC, więc procedura wystawia sygnał start konwersji, czeka 3us... no właśnie, jak można inaczej?
  • Pomocny post
    #15 14374739
    Konto nie istnieje
    Poziom 1  
  • #16 14374747
    dziechu
    Poziom 27  
    Posty: 1609
    Pomógł: 27
    Ocena: 69
    Mam jeszcze inny problem, ale to założę osobny temat. Po optymalizacji przestaje działać wyświetlacz TFT. Nie wiem już gdzie szukać. Opóźnienia przy inicjalizacji, te rzędu kilku-kilkudziesięciu ms są na przerwaniu systick i działają. W ogóle dzieją się różne dziwności, widać sporo podstawowych rzeczy nie wiem o tych procesorach.

    Dodano po 1 [minuty]:

    No źle napisałem, taki skrót myślowy. Chodziło o to że na żądanie, że nie jest dokonywana stale, a nie jednorazowo.
  • #17 14374924
    Konto nie istnieje
    Poziom 1  
  • #18 14375007
    dziechu
    Poziom 27  
    Posty: 1609
    Pomógł: 27
    Ocena: 69
    Chyba czegoś nie rozumiem - obsługa zewnętrznego ADC wymaga wystawienia sygnału start konwersji, konwersja trwa 3us, więc najwcześniej po tym czasie mogę odczytywać ADC po SPI. Nie mogę go odczytywać np. w czasie konwersji. Nie mam pojęcia jak to zrobić nie odmierzając tych 3 us. Nie ma znaczenia czy to będę robił w przerwaniu systick, czy tim, tak czy inaczej muszę wystawić zawsze sygnał start konwersji, po 3 us zdjąć go i odczytywać rejestr, potem przesunąć piksel, znowu start konwersji, 3us, stop konwersji, odczyt. Nie przychodzi mi do głowy jak to ominąć przerwaniami itp. Linijka po każdym przesunięciu piksela wystawia sygnał analogowy, który własnie mierzę tym ADC.

    Dodano po 3 [minuty]:

    Konkretnie typ obsługiwanego ADC to LTC1864
  • Pomocny post
    #19 14375176
    BlueDraco
    Specjalista - Mikrokontrolery
    Posty: 6479
    Pomógł: 939
    Ocena: 421
    3 us to 63 cykle - niby to wcale nie mało dla rdzenia Cortex. Wygeneruj impuls startu konwersji na timerze, w przerwaniu timera na koniec impulsu odpal transmisję, po zakończeniu transmisji z ADC wyzwól ponownie timer. Nie jestem pewny czy zwalnianie uC do 21 MHz to dobry pomysł. Sama transmisja też zajmie trochę czasu, potem obróbka odebranych danych itp... Może się okazać, że wolny zegar procesora spowalnia akwizycję danych.
  • #20 14375292
    dziechu
    Poziom 27  
    Posty: 1609
    Pomógł: 27
    Ocena: 69
    Jak pisałem powyżej, mam zegar zmieniany w zależności od potrzeb na 168MHz, 21MHz i 4 MHz. 21MHz zupełnie wystarcza na obróbkę danych itp. Urządzenie już jest testowane z wykorzystaniem wewnętrznego ADC. Ale ten okazał się trochę za mało dokładny, no i trochę 'pływający'. Zamiast walczyć z z tym wewnętrznym, wolę dać zewnętrzny, uzyskując dodatkowe 4 bity, a urządzenie jest tego warte, sam czujnik kosztował prawie 1000zł. to nie będę żałował 40 na ADC.
  • Pomocny post
    #21 14375689
    Konto nie istnieje
    Poziom 1  
  • #22 14375768
    dziechu
    Poziom 27  
    Posty: 1609
    Pomógł: 27
    Ocena: 69
    atom1477 napisał:
    Wymaga on także żeby przez 2 bity nadawać do układu a potem przejść w odbiór

    Cos chyba źle popatrzyłeś na 1865 - ten dokument opisuje różne przetworniki - popatrz na LTC1864 strona 13 - odczyt jest banalnie prosty, zaraz po zakończeniu konwersji, nawet nie ma co mu nadawać, bo 1864 nie posiada takiej możliwości:)
  • Pomocny post
    #23 14376056
    Konto nie istnieje
    Poziom 1  
  • #24 14376146
    dziechu
    Poziom 27  
    Posty: 1609
    Pomógł: 27
    Ocena: 69
    Obsługa CMOSa jest taka - na opadającym zboczu zegara wystawiany jest impuls START, na następnym zboczu jest kasowany, dalej co cztery impulsy zegara na wyjściu Video pojawia się sygnał analogowy kolejnego piksela, zaczynając od 0 (czy tez wg liczenia producenta od 1). Co cztery takty, pikseli jest 256, więc cały odczyt to 1024 cykle zegara. Czułość CMOSa regulowana jest odstępem impulsów START, czyli częstotliwością odczytu.
  • #25 14376859
    Konto nie istnieje
    Poziom 1  
  • #26 14378089
    dziechu
    Poziom 27  
    Posty: 1609
    Pomógł: 27
    Ocena: 69
    atom1477 napisał:
    A co do czułości to właśnie miałem pytać czy aby ta za duża czułość nie wynikała aby z tego że nie robiłeś ciągłych odczytów z CMOSa


    Nie no takich błędów nie robię:) Linijka albo jest czytana ciagle, ale pierwszy odczyt jest odrzucany. Czułość musi być sciśle określona, bo to przyrząd pomiarowy.

Podsumowanie tematu

✨ Użytkownik poszukuje sposobu na uzyskanie opóźnień rzędu 1-3 µs oraz kilkudziesięciu ns przy taktowaniu procesora STM32F405 na 21 MHz. Zastosowanie timerów zostało odrzucone z powodu zbyt długiego czasu kasowania flagi i ładowania rejestru. Użytkownik rozważa użycie instrukcji NOP, ale obawia się, że może być ona pomijana przez optymalizację kompilatora. W odpowiedziach poruszono kwestie wyłączenia optymalizacji dla poszczególnych funkcji w GCC oraz alternatywne metody generowania opóźnień, takie jak wykorzystanie DWT_CYCCNT do pomiaru cykli procesora. Użytkownik wskazuje na potrzebę synchronizacji zewnętrznego ADC LTC1864, który wymaga 3 µs na konwersję. Dyskutowano również o możliwościach użycia timerów do generowania sygnałów startowych oraz transferu danych przez DMA, co mogłoby uprościć proces akwizycji danych.
REKLAMA