W moim systemie używam I2C i zdaję sobie sprawę, że pod dużym obciążeniem przerywającym (z innych źródeł) komunikacja I2C jest łatwo zakłócana. Czy to oczekiwane zachowanie I2C? Spodziewałbym się pomimo przerwania ładowania, nadal byłoby dobrze, ponieważ I2C nie jest interfejsem o krytycznym znaczeniu dla czasu, zegar jest wyposażony w dane.
Aktualizacja:
Procesor to STM32. Przerwania są spowodowane ADC, nie mogę wyłączyć przerwań podczas zdarzeń odczytu, dlatego muszę znaleźć rozwiązanie, w którym mogę uczynić komunikację i2c bardziej stabilną. STM32 jest urządzeniem nadrzędnym, a urządzenie podrzędne jest innym urządzeniem (akcelerometrem).
Aktualizacja 2:
Kiedy podłączam analizator logiczny do zegara za pomocą małego latającego kabla, problem znika. Co ciekawe, nie ma obciążenia przerwania, odczyt zapisu działa dobrze, gdy obciążenie przerwania nie działa. Jeśli jednak podłączę sondę do zegara, odczyt zapisu działa również pod obciążeniem przerywającym. Myślę, że gdzieś jest problem z pojemnością.
Odpowiedzi:
Jest to problem z oprogramowaniem, spędzasz zbyt dużo czasu na obsłudze przerwań, a twoja procedura I2C nie jest w stanie sobie z tym poradzić (więc to dwie rzeczy, które nie są właściwe). Przeszedłem przez kilka podobnych sytuacji.
Po pierwsze: musisz robić tak mało, jak to możliwe w przerwaniach, tylko odczytywać i przechowywać dane, nie wykonuj żadnego przetwarzania, które możesz wykonać poza ISR, matematyka może zająć DUŻO cykli procesora, a procesor nie może zrobić nic innego podczas tego przerwania.
Po drugie: Zbadaj DMA, aby zautomatyzować różne rzeczy, aby Twoje przerwania stały się prawie automatycznym procesem w tle.
Po trzecie: jeśli I2C jest ważny, włóż TO w przerwę, ale upewnij się, że wypracowałeś priorytety!
Po czwarte: dowiedz się, dlaczego zawodzi twoja procedura I2C, sam I2C może wytrzymać bardzo przerywane czasy, pauzy i oczekiwania itp., Więc twoja procedura może wymagać modyfikacji, aby na to pozwolić.
Po piąte: sprawdź, czy możesz „łączyć” przerwania, może okazać się, że możesz obsłużyć odczyty ADC bardziej wydajnie, lub przełączyć ADC w inny tryb, w którym działa on lepiej przed przerwaniem (np. Poczekaj, aż wszystkie odczyty będą dostępne, następnie czytaj wszystko za jednym razem, zamiast 8 oddzielnych przerwań dla 8 oddzielnych odczytów kanału ADC).
Po szóste: użyj oscyloskopu lub analizatora logicznego i zapasowych styków we / wy na płycie, aby prześledzić, ile czasu spędzasz w każdym fragmencie kodu, i sprawdź, czy możesz go przyspieszyć. (Ustaw wysoki pin, gdy wejdziesz do funkcji / ISR, ustaw ponownie niski przy wyjściu).
Po siódme: Zdecyduj, czy naprawdę musisz tak dużo czytać ADC, czy wolniejsze pogorszenie sytuacji? Jest to sprzeczne z intuicją, ale czasem działa wolniej, w rzeczywistości daje lepsze wyniki, wykonując pracę polegającą na uśrednieniu sygnału i zmniejszeniu skoków / stanów przejściowych, które mogą powodować problemy lub wymagać dodatkowego przetwarzania w celu usunięcia. Ulepszyliśmy procedurę PID sterowania silnikiem, po prostu uruchamiając ją o 1/4 prędkości, uwalniając obciążenie procesora podczas procesu.
źródło
Niewolnik autobusowy, który jest zajęty innymi rzeczami, może taktować czas, aby kupić czas, aż będzie w stanie kontynuować komunikację. Robi to, nie wysyłając natychmiast impulsu zegarowego ACK / NACK, utrzymując komunikację w stanie pośrednim, dopóki nie będzie gotowy do odpowiedzi.
Rozciąganie zegara jest właściwym sposobem radzenia sobie z tego rodzaju sytuacją. Urządzenie, które nie rozciąga się i robi inne złe rzeczy (zawieszanie / restartowanie magistrali, NACK prawidłowy adres lub polecenie itp.) Może być problematyczne i nakłada dodatkowe obciążenie na urządzenie nadrzędne, aby utrzymać porządek (musi powtarzać polecenia , śledź NACK itp.)
źródło
W zależności od możliwości STM32 (nigdy go nie użyłem), możesz wypróbować jedno z poniższych podejść. Jeśli możesz podać więcej szczegółów na temat tego, co próbujesz zrobić, i przekonać cię, dlaczego każde przerwanie jest konieczne w takiej formie, w jakiej go masz, to możesz rozważyć bardziej szczegółową odpowiedź. Jednak w twoim przypadku I2C jest wystarczająco wolne, aby nie stanowiło to problemu z dobrze napisanymi procedurami przerwań.
Przerwania dla czegokolwiek można zwykle wyłączyć. W każdym zwykłym kontrolerze znajduje się najwyżej jedno lub dwa Przerwania Niemaskowalne, z których jedno jest resetowane. Jeśli nie potrzebujesz kontroli czegoś (w twoim przypadku ADC lub I2C), zamień ten kod peryferyjny na taki, który nie używa przerwań, a następnie wyłącz przerwań.
Procedury obsługi przerwań nie powinny być długie. Spróbuj zrobić jak najmniej z samego wektora przerwań. Skrajnie minimalistyczne podejście do przerwań polega po prostu na ustawieniu flagi w ramach procedury obsługi przerwań i powiedzmy, że główna pętla wykonuje wszystkie ciężkie kroki odtąd. To, czego wymaga konkretna architektura aplikacji i oprogramowania układowego, może nie być tak proste, jak to, ale naprawdę warto włożyć wysiłek, aby zobaczyć, ile naprawdę trzeba zrobić z przerwami.
Jeśli masz peryferyjne DMA, użyj tego zamiast przerywania w każdym bajcie. Zazwyczaj łatwiej byłoby umieścić ADC na DMA w przeciwieństwie do I2C, ale różne układy mają różne implementacje. Nie zdziwiłbym się, gdyby istniał czysty sposób na wydzielenie wymiany I2C do DMA. DMA pozwala zmniejszyć liczbę przerwań i pozostawia rdzeń procesora wolny od konieczności radzenia sobie z każdym blokiem danych.
Spróbuj zidentyfikować konkretne przypadki, w których występuje uszkodzenie danych, oraz mechanizm, w którym dochodzi do uszkodzenia danych. Jest to o wiele trudniejsze, ale dzięki kreatywnemu wykorzystaniu nowoczesnego analizatora oscyloskopu / logiki możesz zauważyć niektóre problemy. W szczególności upewnij się, że problem dotyczy czasu, a nie pamięci (co jest możliwe w połączeniu z okropnym kodem i liberalnym kompilatorem)
EDYCJA: Kilka szczegółowych uwag dotyczących tego wystąpienia problemu, z twoich komentarzy do pytania:
źródło
W danym systemie może dochodzić hałas dochodzący do zegara i magistrali danych. Pokazuje to fakt, że Twój program logiczny usuwa problem. Aby uzyskać praktyczne i najszybsze wdrożenie, wystarczy postępować zgodnie ze wskazówkami podanymi przez Twoją obserwację. Na magistrali i2c z implementacją 400 kb / s, w oparciu o podobną obserwację, podłączyłem 2M równolegle z 12pf do ziemi od zegara i punktów danych i stwierdziłem, że problem został rozwiązany. To usuwa / filtruje szum poza pasmem zainteresowania wymaganym dla konkretnej komunikacji i2c. Proszę spróbować i doradzić.
źródło