Strona 1 z 1

Zaskakująca obsługa przerwań od SPI w bibliotece HAL

: czwartek 02 sty 2020, 22:24
autor: elvis
Ostatnio bawię się nieco mikrokontrolerem STM32L496, ale pewnie ten sam feature występuje również w bibliotekach dla innych modeli. Chodzi o aktywne czekanie wewnątrz procedury obsługi przerwania...
Nazwałem to zachowanie "zaskakującym" bo nic innego z cenzuralnych określeń nie przychodziło mi do głowy.

Już tłumaczę gdzie ta ciekawostka mieszka - obsługa SPI jest w pliku stm32l4xx_hal_spi.c. Znajdziemy w nim funkcję o wdzięcznej nazwie SPI_WaitFifoStateUntilTimeout.

Kod: Zaznacz cały

static HAL_StatusTypeDef SPI_WaitFifoStateUntilTimeout(SPI_HandleTypeDef *hspi, uint32_t Fifo, uint32_t State,
                                                       uint32_t Timeout, uint32_t Tickstart);

Sama funkcja to niby nic złego, jest używana do czekania na opróżnienie bufora FIFO w module SPI. Natomiast jej użycie jest już mocno zaskakujące - używana jest mnóstwo razy, ja ją spotkałem w SPI_EndRxTxTransaction, czyli funkcji wywoływanej na zakończenie transmisji danych przy użyciu HAL_SPI_Transmit_IT.

Okazuje się, że taki kod ma dwie wady. Pierwsza, nazwijmy to "optymistyczna" to blokowanie wykonywania kod - udało mi się wygenerować przerwanie, którego obsługa zajmuje 150us, czyli dokładnie 7208 cykli zegara. Przy transmisji 16-bitowych danych i preskalerze /256 tyle zajmuje czekanie aż ten bufor FIFO się opróżni.
W sumie jest jeszcze jedna funkcja z aktywnym czekaniem - SPI_WaitFlagStateUntilTimeout, to co podawałem dotyczy obu "w sumie".

spi_hal_int.PNG


Natomiast druga wada jest znacznie poważniejsza. Koniec nazwy funkcji czyli "UntilTimeout" prawdopodobnie oznacza, że nawet jak coś pójdzie źle, to funkcja nie powinna blokować przerwań w nieskończoność. Niestety autorzy biblioteki pokazali co potrafią... po pierwsze ten "Timeout" jest stały i wynosi 100ms. Nie można go zmienić bez zmiany biblioteki HAL, bo ktoś sobie stałą SPI_DEFAULT_TIMEOUT zdefiniował lokalnie, prywatnie...
Ale w rzeczywistości jest jeszcze gorzej. Ten timeout bazuje na wywołaniu funkcji HAL_GetTick, tylko że przy domyślnych priorytetach przerwań to raczej nie zadziała.

Więc pierwsza nauczka jest taka, że priorytety przerwań właściwie trzeba ustawiać, nawet jeśli nie ma to teoretycznie sensu. No a druga nauczka - to chyba lepiej ostrożnie podchodzić do biblioteki HAL, albo może i nie podchodzić wcale...

Re: Zaskakująca obsługa przerwań od SPI w bibliotece HAL

: czwartek 02 sty 2020, 22:38
autor: dambo
To ja tak obok tematu - z jakiego narzędzia jest ten screen? :)

Re: Zaskakująca obsługa przerwań od SPI w bibliotece HAL

: czwartek 02 sty 2020, 22:41
autor: elvis

Re: Zaskakująca obsługa przerwań od SPI w bibliotece HAL

: czwartek 02 sty 2020, 22:49
autor: ZbeeGin
Hmmm... Z tego co napisali w notce wydawniczej:
In 2 lines transmission configuration, ensure RXFIFO is empty at the end of transmission. Add SPI_WaitFifoStateUntilTimeout (SPI_FLAG_FRLVL) call.

Problem teoretycznie powinien dotyczyć przypadku pracy SPI na dwóch liniach, czyli w half-dupleksie/simpleksie. I o ile można zrozumieć opróżnianie bufora FIFO w trybie half-dupleks gdzie dane biegają w obie strony po jednym przewodzie i nie może być kolizji - bo w FIFO coś tam zostało; to nieco dziwne by było stosowanie tego do simpleksu gdzie albo nadajemy, albo odbieramy.

Wydaje mi się, że chcieli poprawić half-duplex ale dostało się rykoszetem też trybowi simplex...

Re: Zaskakująca obsługa przerwań od SPI w bibliotece HAL

: czwartek 02 sty 2020, 23:02
autor: elvis
Jak dla mnie niezależnie od trybu to oczekiwanie nie powinno blokować przerwań. Tym bardziej, że timeout wymaga obsługi przerwań od systicka i jest koszmarnie długi. W każdym razie chciałem napisać co znalazłem, może się komuś przyda :)