Kanał - ATNEL tech-forum
Wszystkie działy
Najnowsze wątki



Teraz jest 19 kwi 2024, o 18:35


Strefa czasowa: UTC + 1





Utwórz nowy wątek Odpowiedz w wątku  [ Posty: 23 ] 
Autor Wiadomość
PostNapisane: 6 cze 2018, o 09:56 
Offline
Użytkownik

Dołączył(a): 31 mar 2017
Posty: 156
Pomógł: 0

Mam pytanie o działanie przerwania.
Mając kod przerwania postaci:
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.
kolejne odliczanie timera zaczyna się od momentu wystąpienia poprzedniego przerwania (od miejsca TIM_ClearITPendingBit(TIM5, TIM_IT_Update)), czy od momentu zakończenia wykonywania kodu przerwania ("koniec kodu przerwania")? Co się dzieje w przypadku, kiedy "moje operacje" zajmują więcej czasu, niż odstęp pomiędzy kolejnymi przerwaniami? A może linia TIM_ClearITPendingBit(TIM5, TIM_IT_Update) powinna być na końcu?



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 6 cze 2018, o 21:13 
Offline
Użytkownik

Dołączył(a): 31 mar 2017
Posty: 156
Pomógł: 0

Czyli raczej nie mam sytuacji, w której nie zdąży się wykonać kod, ale jeszcze dokładnie to sprawdzę.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 7 cze 2018, o 07:31 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 15 lut 2017
Posty: 369
Lokalizacja: Gliwice
Pomógł: 34

dambo napisał(a):
odliczanie dzieje się natychmiast - w kodzie przerwania jedynie czyścisz flagę, która informuje, że wystąpił event.
Przerwania powinny się zazwyczaj wykonywać bardzo szybko, nie powinno się ich blokować jakimś dużym kawałkiem kodu.

To bardzo ogólna zasada stosowana tam gdzie nie można ustawiać priorytetów przerwań i wywłaszczeń, np w programowaniu AVR.
Ponieważ piszemy w wątku o STM32 to w wypadku tychże procków najczęściej nie ma zastosowania.
Nawet wręcz przeciwnie, można spotkać zalecenia mówiące, żeby w ogóle pisać w przerwaniach, z pominięciem pętli w main.
Sam zrobiłem już kilka projektów na STM32 i wydaje mi się, że zalecenia te są całkiem sensowne.
Szczególnie przydatne jest tutaj pojęcie wywłaszczenia przerwań.


Autor postu otrzymał pochwałę


Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 7 cze 2018, o 20:12 
Offline
Użytkownik

Dołączył(a): 31 mar 2017
Posty: 156
Pomógł: 0

Robię filtry cyfrowe i w przerwaniu wykonuję mnożenia, dodawania i przesuwanie wartości w tablicy. Chciałbym uzyskać fs=44100Hz dla różnych (niewielkich) rzędów filtrów. Ale okazuje się, że już przy ok. 10. rzędzie FIR mam nieprawidłowe wartości.
Sprawdzam działanie przerwania zmieniając stan pinu, który badam oscyloskopem. I okazuje się, że częstotliwość zmian jest ograniczona i od pewnego momentu niezależna od ustawień przerwania. Chodzi mi o to, że gdy już uzyskam maksymalną częstotliwość, to dalsze zmniejszanie tim.TIM_Period nie powoduje zmian tej częstotliwości.
Myślałem, że jeśli kolejne przerwanie wystąpi przed wystawieniem wartości na pinie, to nic się nie będzie działo, bo zacznie się kolejne przerwanie, a dopiero na jego końcu mam zmianę stanu bitu. Dlaczego tak się dzieje? Czyżby gdzieś była zapamiętywana komenda do wystawienia stanu wysokiego lub niskiego i po prostu jest wykonywana z opóźnieniem? A może to szybkość zmian stanu pinu jest ograniczona (wychodzi mi ok. 25kHz)?



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 8 cze 2018, o 08:41 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 11 mar 2014
Posty: 1475
Pomógł: 167

radek04 napisał(a):
A może to szybkość zmian stanu pinu jest ograniczona (wychodzi mi ok. 25kHz)?
Takie prędkości to uzyskujesz bez żadnego problemu na AVRze. Więc na pewno na STMie musisz coś źle ustawiać.
Jak masz ustawiony sygnały zegarowe?
Daj trochę więcej informacji o kodzie (szczególnie inicjalizacji) oraz przerwaniu, to może coś Ci podpowiemy :)
A najlepiej obetnij kod tylko do tego przerwania i sterowania pinem. I sprawdź czy nadal nie działa. Jak tak, to wrzuć na forum a na pewno ktoś Ci pomoże.

--
Pozdrawiam,
Robert



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 8 cze 2018, o 16:09 
Offline
Użytkownik

Dołączył(a): 31 mar 2017
Posty: 156
Pomógł: 0

Zostawiłem w przerwaniu tylko sterowanie pinem i faktycznie udaje się uzyskać większe szybkości (ok 700kHz).

Jest to dla mnie wystarczające, więc problemem chyba jest sam kod występujący w przerwaniu:
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


W razie czego wrzucam konfigurację wszystkich używanych modułów:
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 8 cze 2018, o 18:20 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 15 lut 2017
Posty: 369
Lokalizacja: Gliwice
Pomógł: 34

Wg mnie popełniasz tutaj spory błąd w założeniach, tzn nie używasz DMA do zbierania próbek, stąd pewnie problemy z wydajnością.
Zaleta użycia DMA byłaby tutaj taka, że w momencie przeliczania, mnożenia itp, możesz już zbierać próbki do następnych działań, bez straty czasu procesora. Przeliczanie nie wymaga ścisłych zależności czasowych, może być przerywane innymi zdarzeniami, natomiast zbieranie próbek to i owszem. W F3 masz jeszcze sporo dostępnych kanałów DMA. Druga sprawa, ale już bardziej indywidualna, osobista, to ten bagaż w postaci bibliotek :)

Z mało istotnych błędów, to niepotrzebnie dwa razy włączasz zegar dla ADC1, ale to takie czepianie się tylko :)
Dziwnie też dla mnie wygląda konfiguracja zegara dla portów, też jakby dwa razy to włączane, ale z innych funkcji.
Nie znam niestety STD Periph, więc nie wiem, może to poprawne jest. Na rejestrach bylaby to jedna linijka.
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 8 cze 2018, o 18:52 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 04 paź 2011
Posty: 8583
Pomógł: 337

Zealota napisał(a):
Na rejestrach bylaby to jedna linijka.


z std to też jedna linijka .. a nawet jej połowa ...

Tymczasem kod powyższy jest przekombinowany , i pozbawiony logiki ...
zegar wystarczy 1 raz włączyć dla urządzeń nie trzeba robić funkcji i podprogramów ... co zbędnie komplikuje czytanie kodu go zaciemnia
po co kolejne włączanie zegarów w konfiguracji LCD ??

skoro używasz SPI do LCD to nie możesz zdefiniować pinów ??

ale dobra ... bo zaraz mnie spece od rejestrów zlinczują ... że wytykam błędy ...

(jak nie wiesz jak co uruchomić podglądnij sobie w choćby przykładach od STM -- to nie boli )

_________________
[b]San Escobar! Patria mia! Tu eres como la salud.[/b]



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 8 cze 2018, o 20:59 
Offline
Użytkownik

Dołączył(a): 31 mar 2017
Posty: 156
Pomógł: 0

Co do kodu to przyznaję się, że był pisany przez dwóch ludzi i składany z mniejszych fragmentów, stąd te powtórzenia. Jeśli chodzi o SPL, to długa historia. Powoli muszę kończyć projekt i nie bardzo mam czas na rewolucyjne zmiany.
Obliczenia muszą wykonywać się pomiędzy pomiarami i wystawiać DAC na bieżąco. Nie robiłem nigdy DMA. W czym ono dokładnie pomoże?



Ostatnio edytowano 8 cze 2018, o 21:13 przez radek04, łącznie edytowano 1 raz

Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 8 cze 2018, o 21:06 
Offline
Użytkownik

Dołączył(a): 25 lip 2013
Posty: 2561
Pomógł: 126

W transferach danych bez udziału procka.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 8 cze 2018, o 21:20 
Offline
Użytkownik

Dołączył(a): 31 mar 2017
Posty: 156
Pomógł: 0

Czyli do odczytu ADC powinienem użyć DMA, tak? Ale jeśli czegoś nie pomyliłem, to odczyt zajmuje chyba kilkanaście cykli zegara (nie wiem ile ich zapis), więc niewiele zaoszczędzę, a potrzebuję 2x większej szybkości wszystkich operacji.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 8 cze 2018, o 22:04 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 15 lut 2017
Posty: 369
Lokalizacja: Gliwice
Pomógł: 34

Ile robisz próbek poprzez ADC? Jeśli kilka to faktycznie nie ma sensu użyć DMA, ale jeśli jest ich kilkaset, to należy użyć DMA.
Dla 512 próbek i częstotliwości próbkowania 44100 Hz musisz robić cały pomiar przez 512 * 22 us = 11 ms, zapełniając bufor aż po ostatnią próbkę. Ilość próbek jest zdefiniowana w rejestrze kontrolera DMA. Nie ma sensu aby co 22 us wchodzić w przerwanie i coś tam mnożyć. Lepiej mnożyć przez te 11 ms zbierając próbki już do następnych przeliczeń. Dlatego należy użyć DMA.
Pomiar co 22 us oczywiście wyzwalany jest przez timer, a włączone DMA pozwala zdjąć procesor z konieczności kopiowania danych z rejestru ADC do pamięci RAM.
Warto przeglądnąć to:
https://forbot.pl/blog/kurs-stm32-f4-5- ... io-id13099

Co prawda to w HALu, ale wydaje mi się że sporo musisz nadrobić. Szybkie przejście z HAla na STD nie powinno sprawić kłopotu.

Może zacząć od tego:
https://embedds.com/multichannel-adc-us ... -on-stm32/



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 9 cze 2018, o 07:08 
Offline
Użytkownik

Dołączył(a): 31 mar 2017
Posty: 156
Pomógł: 0

Wykonuję tylko 1 pomiar, przetwarzanie i wysłanie na DAC w każdym przerwaniu. Wydaje mi się, że sporo czasu może zajmować przesuwanie elementów tablicy.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 10 cze 2018, o 06:23 
Offline
Użytkownik

Dołączył(a): 31 mar 2017
Posty: 156
Pomógł: 0

Myślicie, że powinienem użyć DMA dla pojedynczego odczytu? A może jakoś zoptymalizować inne operacje? Podobno zamiast przesuwania elementów tablicy, można wykorzystać wskaźniki, ale nie do końca wiem jak.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 10 cze 2018, o 20:59 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 15 lut 2017
Posty: 369
Lokalizacja: Gliwice
Pomógł: 34

radek04 napisał(a):
Myślicie, że powinienem użyć DMA dla pojedynczego odczytu? A może jakoś zoptymalizować inne operacje? Podobno zamiast przesuwania elementów tablicy, można wykorzystać wskaźniki, ale nie do końca wiem jak.

A może napisz po prostu co właściwie ten program ma robić, bo wydaje mi się, że nie do końca wiemy.
Pisałeś o filtrze cyfrowym, ale z tego co rozumiem to po każdym pomiarze z ADC już chcesz od razu coś przeliczać i od razu wyrzucać do DACa. Wg mnie tak się tego nie powinno robić. Pisałem już o tym, zbierasz porcję danych, zaczynasz przeliczać, w czasie przeliczania zbierasz kolejną porcję danych.
Wygląda na to jakbyś chciał zrobić coś w stylu korektora dźwiękowego o bardzo niskim opóźnieniu.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 12 cze 2018, o 06:46 
Offline
Użytkownik

Dołączył(a): 31 mar 2017
Posty: 156
Pomógł: 0

Masz rację. Założenie jest takie, by filtr działał na bieżąco "w czasie rzeczywistym". Ale jeśli z pewnym niewielkim opóźnieniem także uda się uzyskać sygnał ciągły bez utraty żadnego fragmentu, to też będzie w porządku.
Ale chyba tak się nie da, prawda?

Program ma pokazywać działanie filtru. Na oscyloskopie do jednego kanału podany jest sygnał wejściowych, a do drugiego wyjściowy - albo identyczny z wejściowym, albo tłumiony(częściowo, lub całkowicie). Zastosowanie bardziej edukacyjne, niż praktyczne.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 12 cze 2018, o 10:42 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 15 lut 2017
Posty: 369
Lokalizacja: Gliwice
Pomógł: 34

No to teraz sporo się wyjaśniło.
Nie mam niestety doświadczenia w budowaniu filtrów cyfrowych, może poza prostymi "średnimi", ale można trochę podywagować o Twoim rozwiązaniu.
Jak już wyliczałem, dla próbkowania 44100 Hz należy zbierać sample co 22 us, czyli masz mniej więcej tyle czasu na zebranie danych i obliczenia.
Oczywiście to wszystko przy założeniu, że procesor nic innego nie robi. Spójrzmy na obsługę przerwania:
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.

Można spróbować kilku optymalizacji.
1. Usunięcie typu double. Procki STM32 nie są zoptymalizowane do tego typu, czy faktycznie potrzebujesz tak dużego zakresu do swoich obliczeń? Może uint32_t wystarczy, a może float32_t? O tym drugim nieco niżej.

2. Używasz pętli, można spróbować rozwinąć pętle, szczególnie te duże wartości 10 i więcej, można by rozpisać do prostych poleceń, tak by procesor nie tracił czasu na skoki. Wielkość kodu wzrośnie, a można zaoszczędzić trochę czasu procesora.
Można stworzyć funkcje static inline z rozwinięciami, zależne od rzędu filtru.

3. Nic nie piszesz o optymalizacjach, które zastosowałeś.
Czy próbowałeś używać bibliotek matematycznych dostarczanych z CMSIS?
Czy włączasz obsługę sprzętową zmiennoprzecinkową, możesz o tym poczytać tutaj:
https://forum.sunduino.pl/viewtopic.php?f=9&t=59
Jeśli włączysz obsługę FPU, to jest szansa, że operacje na float32_t przyśpieszą.

4. Może w ogóle zainteresuj się CMSIS, masz tam obsługę filtrów cyfrowych zoptymalizowaną pod STM32:
https://developer.arm.com/embedded/cmsis
Sekcja:
CMSIS-DSP: Fast implementation of digital signal processing
Lepiej tego pewnie nie napiszesz (a kto tutaj napisze :) ), niestety to podejście wymaga studiowania tematu.
Ja to już troszkę liznąłem, ale nie na tyle żeby wiele podpowiedzieć.

Mogę napisać dodatkowo, że biblioteka jest obszerna, optymalizacje są zależne od wybranej precyzji (8, 16, 32 bitowej).
Mamy tam szereg podstawowych, zoptymalizowanych funkcji matematyczny jak sinus, średnia, tranformata Fouriera, filtry cyfrowe itp.


Autor postu otrzymał pochwałę


Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 12 cze 2018, o 12:10 
Offline
Użytkownik

Dołączył(a): 31 mar 2017
Posty: 156
Pomógł: 0

Świetne rady. Co do rozpisania pętli (o ile dobrze to rozumiem), to raczej się nie uda, bo program ma być "elastyczny" i przystosowany do uzycia dowolnego (acz ograniczonego co do wielkości) rzędu.
Biblioteka CMSIS też chyba nie przejdzie z powodu narzucenia, by kod filtru był "widoczny".
Najbardziej mnie zainteresowała funkcja wspomagania sprzętowego. Pozostałe rady też spróbuje zastosować. Niestety do piątku jestem poza domem, ale postaram się w miarę możliwości coś poprawić.

Edit: Wspomaganie sprzętowe mam włączone.



Ostatnio edytowano 12 cze 2018, o 12:28 przez radek04, łącznie edytowano 1 raz

Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 12 cze 2018, o 12:26 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 15 lut 2017
Posty: 369
Lokalizacja: Gliwice
Pomógł: 34

radek04 napisał(a):
Świetne rady. Co do rozpisania pętli (o ile dobrze to rozumiem), to raczej się nie uda, bo program ma być "elastyczny" i przystosowany do uzycia dowolnego (acz ograniczonego co do wielkości) rzędu.

Jeżeli rząd jest ograniczony do np 20, to przygotowanie 11 "rozpisanych" funkcji (załóżmy powyżej 9 rzędu, które to załóżmy już są problematyczne ) to nie będzie problem jeśli masz sporo pamięci FLASH.
Jeśli podejrzysz kody CMSIS to zauważysz, że są tam tablice stałych o wielkości nawet do 8192 słów, czy też "floatów"
To są właśnie metody na przyśpieszanie kodu poprze eliminacje skoków.
Oczywiście najlepiej jak zrobisz sobie testy i pomierzysz czasy, czy faktycznie będziesz miał zysk.

radek04 napisał(a):
Biblioteka CMSIS też chyba nie przejdzie z powodu narzucenia, by kod filtru był "widoczny".
Najbardziej mnie zainteresowała funkcja wspomagania sprzętowego. Pozostałe rady też spróbuje zastosować. Niestety do piątku jestem poza domem, ale postaram się w miarę możliwości coś poprawić.

Nic nie szkodzi, żebyś sobie podejrzał funkcje do filtrów w CMSIS, może sam wpadniesz na dodatkowe optymalizacje.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 12 cze 2018, o 12:34 
Offline
Użytkownik

Dołączył(a): 31 mar 2017
Posty: 156
Pomógł: 0

Mam w projekcie folder CMSIS (używam SW4STM32), ale nie ma w nim przykładów. Gdzie je mogę znaleźć?
W przerwaniu mogę wywoływać funkcję static inline?



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 12 cze 2018, o 15:50 
Offline
Użytkownik

Dołączył(a): 25 lip 2013
Posty: 2561
Pomógł: 126

Popatrz jak się tego typu filtrowanie robi na innych prockach np DSPIC, może coś wykorzystasz a może zmienisz procka? ;)



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 12 cze 2018, o 20:06 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 15 lut 2017
Posty: 369
Lokalizacja: Gliwice
Pomógł: 34

radek04 napisał(a):
Mam w projekcie folder CMSIS (używam SW4STM32), ale nie ma w nim przykładów. Gdzie je mogę znaleźć?
W przerwaniu mogę wywoływać funkcję static inline?

Najlepiej ściągnij CubeMX i gdy wygenerujesz jakiś projekt do System Workbench to zostaną pobrane paczki dla STM32F4.
W katalogu użytkownika znajdziesz taką ścieżkę:
STM32Cube\Repository\STM32Cube_FW_F4_V1.18.0\Drivers\CMSIS
Nr biblioteki może się różnić.

W środku będzie pełna biblioteka DSP_lib. Opis biblioteki, w jęz. angielskim, już w tym wątku podsyłałem.
Static inline możesz wywoływać w przerwaniu, bo czemu by nie?



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 15 cze 2018, o 15:16 
Offline
Użytkownik

Dołączył(a): 31 mar 2017
Posty: 156
Pomógł: 0

Próbowałem różnych rozwiązań i zdecydowanie najwięcej korzyści przyniosła zmiana typu danych na float. Przy FIR udało mi się uzyskać 50. rząd dla szybkości próbkowania 44100 Hz. Co prawda dla IIR to tylko 12. rząd, ale może wystarczy.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
Wyświetl posty nie starsze niż:  Sortuj wg  
Utwórz nowy wątek Odpowiedz w wątku  [ Posty: 23 ] 

Strefa czasowa: UTC + 1


Kto przegląda forum

Użytkownicy przeglądający ten dział: Brak zidentyfikowanych użytkowników i 2 gości


Nie możesz rozpoczynać nowych wątków
Nie możesz odpowiadać w wątkach
Nie możesz edytować swoich postów
Nie możesz usuwać swoich postów
Nie możesz dodawać załączników

Szukaj:
Skocz do:  
Sitemap
Technologię dostarcza phpBB® Forum Software © phpBB Group phpBB3.PL
phpBB SEO