Skocz do zawartości

STM32F7 Zbyt mała szybkość zapisu danych z czujników I2C na kartę SD


radek04

Pomocna odpowiedź

Dnia 27.11.2022 o 00:06, radek04 napisał:

podczas 1-minutowych testów z fs=400 Hz całkowity czas operacji wynosi ok. 65 sekund. Np. dla 100 Hz jest to dokładnie 60 sekund. Zatem program "nie wyrabia" owych 400 Hz.

Możesz napisać co to oznacza? Jak wyznaczasz minutę w tych testach, a jak 65 sekund? Szczególnie w świetle informacji że masz dokładnie te same dane pod rząd, chciałbym zrozumieć na ile jesteś pewien, że nie nadążasz z odczytem. A nie na przykład, że ze masz czasami podwójne zapisy. Po w tym drugim przypadku trzeba szukać problemu zupełnie gdzie indziej i rozmowy o DMA itd należy odłożyć na bok. 

Link do komentarza
Share on other sites

Masz rację, napisałem to bardzo niejasno. Już tłumaczę.

Gdy ustalam próbkowanie na 400 Hz, przerwanie timerawykonuje się co 2,5 ms. Po uruchomieniu timera załączam zewnętrzny zegar (mało dokładny sposób, ale przy różnicach wynoszących kilka sekund daje jasny komunikat). W każdym takim przerwaniu inkrementuję zmienną pomocniczą. Gdy zmienna osiągnie wartość 24000 (60 s * 400 pomiarów), program się kończy, a ja wyłączam zewnętrzny zegar.
Jeśli nie ma żadnych opóźnień, 24000 przerwań powinno wykonać się dokładnie w minutę. Zewnętrzny zegar pokazuje kilka sekund więcej.

Swoją drogą mnie samego dziwiło takie zachowanie, ponieważ byłem pewny, że kolejne przerwanie wykona się niezależnie od tego, czy wszystkie operacje zostały zrealizowane, czy nie. Ale okazuje się, że jeśli w bloku przerwania zegarowego są czasochłonne operacje, przerwanie wykonuje się rzadziej niż powinno.
Gdy dane przesyłałem przez UART, niektóre pomiary były pomijane (np. przesyłało co trzecią paczkę danych), ale gdy zapisuję je na karcie, przy 400 Hz zawsze mam wszystkie 24000 paczek zapisanych, tylko trwa to dłużej niż powinno.

Link do komentarza
Share on other sites

1 godzinę temu, radek04 napisał:

Swoją drogą mnie samego dziwiło takie zachowanie, ponieważ byłem pewny, że kolejne przerwanie wykona się niezależnie od tego, czy wszystkie operacje zostały zrealizowane, czy nie.

Tu akurat chyba nie ma zaskoczenia. Wszystkie mikrokontrolery jakie znam działają tak samo. Jest wektor przerwań, w którym są wskaźniki na funkcję przerwań. Gdy przerwanie jest włączone i niemaskowane, to gdy nastąpi, sprzęt wywołuje funkcję spod danego miejsca z wektora przerwań. Przed wejściem do funkcji są odpowiednie dane odkładane na stos i przerwanie jest maskowane. Po zakończeniu funkcji dane są zdejmowane ze stosu i przerwanie jest odmaskowywane.

1 godzinę temu, radek04 napisał:

Ale okazuje się, że jeśli w bloku przerwania zegarowego są czasochłonne operacje, przerwanie wykonuje się rzadziej niż powinno.

Liczba operacji w funkcji obsługi przerwania powinna być minimalna. Bardzo często stosuje się trick, że ustawia się globalna zmienną volatile i samą obsługę wykonuje się w pętli głównej.

 

Wracając do Twojego zagadnienia, aby nie mówić problemu... Uważam, że nie powinieneś robić absolutnie żadnych operacji na danych z czujnika chyba, że to zmniejsza ich ilość. Raw data czytasz i zapisujesz. Jak mogłoby to działać? DMA pisze do bufora okrężnego. ISR timera triggeruje DMA. ISR DMA sprawdza, który czujnik obsługuje i po zakończeniu czytania z jednego czujnika, rozpoczyna transmisję z kolejnego. Przeczytaniu wszystkich czekamy na przerwanie z timera. Za to w pętli głównej zajmujemy się wypychaniem danych z bufora okrężnego. W ISR timera sprawdzasz czy DMA jest używane oraz czy bufor jest pusty czy pełny i zapalasz odpowiednią diodę - zielona lub czerwona. Jak bufor jest pusty i DMA nie chodzi to Twoim wąskim gardłem jest czytanie z czujników. Jak bufor jest pełny lub DMA jest wciąż używane - Twoim wąskim gardłem jest wypychanie danych na kartę. 

EDIT: https://github.com/STMicroelectronics/STM32CubeF0/tree/4390ff6bfb693104cf97192f98c3dc9e3a7c296a/Projects/STM32F072B-Discovery/Examples/I2C/I2C_TwoBoards_ComDMA 

Edytowano przez pmochocki
Link do komentarza
Share on other sites

49 minut temu, pmochocki napisał:

Uważam, że nie powinieneś robić absolutnie żadnych operacji na danych z czujnika chyba, że to zmniejsza ich ilość. Raw data czytasz i zapisujesz. Jak mogłoby to działać? DMA pisze do bufora okrężnego...

Jedyne co robię na danych, to zapisuję je na kartę w formacie HEX z użyciem funkcji sprintf. Już sprawdzałem - to nie ona powoduje tutaj opóźnienia.
DMA w żaden sposób nie udało mi się uruchomić. Albo jest jakiś błąd w oprogramowaniu IDE/bibliotece do F7, albo - co bardziej prawdopodobne - nie umiem tego zrobić. Próbowałem z kilkoma tutorialami i nic.

Link do komentarza
Share on other sites

Zarejestruj się lub zaloguj, aby ukryć tę reklamę.
Zarejestruj się lub zaloguj, aby ukryć tę reklamę.

jlcpcb.jpg

jlcpcb.jpg

Produkcja i montaż PCB - wybierz sprawdzone PCBWay!
   • Darmowe płytki dla studentów i projektów non-profit
   • Tylko 5$ za 10 prototypów PCB w 24 godziny
   • Usługa projektowania PCB na zlecenie
   • Montaż PCB od 30$ + bezpłatna dostawa i szablony
   • Darmowe narzędzie do podglądu plików Gerber
Zobacz również » Film z fabryki PCBWay

18 minut temu, radek04 napisał:

Jedyne co robię na danych, to zapisuję je na kartę w formacie HEX z użyciem funkcji sprintf. Już sprawdzałem - to nie ona powoduje tutaj opóźnienia.

Na razie nie wiemy co jest wąskim gardłem, ale masz racje, że to może być odczyt z czujników. Ja bym to wyrzucił na razie, ale to jest sprawa drugorzędna. 

20 minut temu, radek04 napisał:

DMA w żaden sposób nie udało mi się uruchomić. Albo jest jakiś błąd w oprogramowaniu IDE/bibliotece do F7, albo - co bardziej prawdopodobne - nie umiem tego zrobić. Próbowałem z kilkoma tutorialami i nic.

No jest błąd w CubeMX:
https://electronics.stackexchange.com/questions/602056/stm32f7-i2c-master-transmission-using-dma-does-not-work
na ST Comunity temat utknął:
https://community.st.com/s/question/0D53W00001HIiCSSA1/stm32f7-i2c-master-transmission-using-dma-does-not-work
więc możliwe, że błąd nadal tam jest.

  • Lubię! 1
Link do komentarza
Share on other sites

9 minut temu, pmochocki napisał:

Tak, widziałem, że w kilku miejscach ludzie szukali rozwiązań i nigdzie skutecznego nie znalazłem. Jutro powinno dotrzeć Nucleo H7, tam sprawdzę. Układ ten jest też szybszy i będę miał 4 linie I2C. Liczę, że to pomoże.

Link do komentarza
Share on other sites

3 minuty temu, szymonw napisał:

A faktycznie nie zauważyłem ,że jest timer_tim10++; ale jest następna linijka  if (timer_tim10 <= 6*4000).Czy nie da się zastąpić liczbą 24000.Jedna operacja mniej bo to 6*4000 to chyba  mnożenie prawda?Następna linia }else if (timer_tim10 == 6*4000+1).Czy nie lepiej zastąpić to takim zapisem  else if (timer_tim10 > 24000).W tym miejscu procesor musi wykonać mnożenie i dodawanie. Z mojego eksperymentu wynika,że użycie zegara wewnętrznego procesora skutkuje gorszą dokładnością.Dużą dokładność daje crystal/ceramic resonator.Jeśli nie masz wlutowanego rezonatora to trzeba wlutować rezonator i dwa kondensatory.W moim przypadku różnica była rzędu kilku tysięcy na 17,2mln zapisów przy rezonatorze wewnętrznym a przy zewnętrznym  mniej niż 20 ppm.Jeszcze jedno kiedyś gdzieś wyczytałem ,że  zapis ++timer_tim10; jest szybszy niż ten,który stosujesz.Uzasadnienia nie pamiętam.

Tak, wiem. Te zapisy to tak tylko do testów na razie. Ale szczerze wątpię, by miało to aż takie znaczenie. Natomiast zasadniczo masz rację.

Link do komentarza
Share on other sites

8 minut temu, szymonw napisał:

Czy nie da się zastąpić liczbą 24000.Jedna operacja mniej bo to 6*4000 to chyba  mnożenie prawda?Następna linia }else if (timer_tim10 == 6*4000+1).Czy nie lepiej zastąpić to takim zapisem  else if (timer_tim10 > 24000)

To nie ma znaczenia, kompilator wyliczy to działanie i wstawi tam stałą.

  • Lubię! 1
Link do komentarza
Share on other sites

11 godzin temu, pmochocki napisał:

No jest błąd w CubeMX:

To akurat najmniejszy problem - w przypadku STM32L4 też pojawiały się problemy z kodem generowanym przez CubeMX i jedna wersja działała poprawnie, a po aktualizacji niekoniecznie. Jednak dodanie inicjalizacji zegara, albo zmiana kolejności wywołań funkcji nie są raczej wielkim wyzwaniem.

Ale proponuję sprawdzić jak biblioteka Cube obsługuje spójność pamięci cache... może dlatego tak mało jest kursów programowania STM32F7 i H7 🙂

Edytowano przez Elvis
  • Lubię! 1
Link do komentarza
Share on other sites

Dnia 28.11.2022 o 20:13, pmochocki napisał:

Gdy przerwanie jest włączone i niemaskowane, to gdy nastąpi, sprzęt wywołuje funkcję spod danego miejsca z wektora przerwań. Przed wejściem do funkcji są odpowiednie dane odkładane na stos i przerwanie jest maskowane. Po zakończeniu funkcji dane są zdejmowane ze stosu i przerwanie jest odmaskowywane.

Czy dobrze rozumiem, że operacja, która została - nomen omen - przerwana przez przerwanie wykonujące coś innego, po zakończeniu instrukcji w przerwniu wróci w odpowiednim momencie do realizacji swojego kodu? Czy to raczej ryzykowne i nieprzewidywalne?

Chodzi mi o zapis na kartę - powiedzmy, że 60% danych się zapisało, zapis został przerwany przez odczyt z czujników (wywoływany w przerwaniu timera). Czy po zakończeniu odczytu na kartę zostanie zapisane pozostałe 40% danych, czy to tak nie zadziała?

Link do komentarza
Share on other sites

51 minut temu, radek04 napisał:

Czy dobrze rozumiem, że operacja, która została - nomen omen - przerwana przez przerwanie wykonujące coś innego, po zakończeniu instrukcji w przerwniu wróci w odpowiednim momencie do realizacji swojego kodu? Czy to raczej ryzykowne i nieprzewidywalne?

Tak to zadziała, po to jest stos, aby wróciło we właściwe miejsce.

52 minuty temu, radek04 napisał:

Chodzi mi o zapis na kartę - powiedzmy, że 60% danych się zapisało, zapis został przerwany przez odczyt z czujników (wywoływany w przerwaniu timera). Czy po zakończeniu odczytu na kartę zostanie zapisane pozostałe 40% danych, czy to tak nie zadziała?

Tu jest potencjalnie inny problem. To że zapis zostanie przerwany to jest ok. Ale czy zawsze możesz przerwać taki zapis? Jeśli używasz jakiejś biblioteki to ona powinna zadbać o to, aby maskować przerwania jeśli w danym momencie nie można przerwać operacji. Może być też tak, że jak używasz, DMA i wsparcia sprzętowego, że przerywanie nie jest problemem, ale to jest potencjalny problem, który trzeba mieć na uwadzę, szczególnie jakby coś zachowywało się "dziwnie". 

Link do komentarza
Share on other sites

14 godzin temu, pmochocki napisał:

Tu jest potencjalnie inny problem. To że zapis zostanie przerwany to jest ok. Ale czy zawsze możesz przerwać taki zapis? Jeśli używasz jakiejś biblioteki to ona powinna zadbać o to, aby maskować przerwania jeśli w danym momencie nie można przerwać operacji. Może być też tak, że jak używasz, DMA i wsparcia sprzętowego, że przerywanie nie jest problemem, ale to jest potencjalny problem, który trzeba mieć na uwadzę, szczególnie jakby coś zachowywało się "dziwnie". 

No i chyba właśnie tak dziwnie się zachowuje.

Mimo użycia zapisu na kartę w trybie DMA (pewności nie mam, że tak to się odbywa, ale wszystkie ustawienia i pliki mam zmienione na DMA), operacja ta jakby blokowała inne instrukcje...

W wątku STM32H7 Zapis na kartę SD z użyciem FatFs - wykorzystanie DMA kontynuuję walkę na H7 i proponuję tam też kontynuować dyskusję.

Link do komentarza
Share on other sites

Dołącz do dyskusji, napisz odpowiedź!

Jeśli masz już konto to zaloguj się teraz, aby opublikować wiadomość jako Ty. Możesz też napisać teraz i zarejestrować się później.
Uwaga: wgrywanie zdjęć i załączników dostępne jest po zalogowaniu!

Anonim
Dołącz do dyskusji! Kliknij i zacznij pisać...

×   Wklejony jako tekst z formatowaniem.   Przywróć formatowanie

  Dozwolonych jest tylko 75 emoji.

×   Twój link będzie automatycznie osadzony.   Wyświetlać jako link

×   Twoja poprzednia zawartość została przywrócona.   Wyczyść edytor

×   Nie możesz wkleić zdjęć bezpośrednio. Prześlij lub wstaw obrazy z adresu URL.

×
×
  • Utwórz nowe...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.