Atlantis
Guest
Tue Oct 25, 2022 8:47 am
Ostatnio spędziłem trochę czasu na raczej bezowocnych eksperymentach z
RAW API biblioteki lwIP (to oparte na callbackach, przeznaczone do pracy
bezpośrednio na krzemie). Wszystko rozbija się o fakt, że to API nie
pozwala mi w łatwy sposób pobierać z bufora dowolnej liczby bajtów
wtedy, kiedy jest to dla mnie wygodne - kiedy przychodzi nowa paczka
powinienem ją jak najszybciej obsłużyć, zwolnić pamięć i poprosić o
kolejną. Takie podejście wymagało dość gruntownego przepisania kodu
mojej aplikacji, która potem nie działała zbyt sprawnie.
Postanowiłem w końcu spróbować z FreeRTOS-em, aby mieć dostęp do
bardziej standardowego API opartego na socketach. Przeklikałem się
ponownie przez konfigurację z mojego projektu w STM32CubeMX, dodając
FreeRTOS-a. Zmieniłem timebase source z SysTick na Timer1 oraz
utworzyłem domyślny task.
Chyba jakiś bug w CubeMX sprawił, że w konfiguracji lwIP pod definicję
RTOS_USE_NEWLIB_REENTRANT został podstawiony jakiś dziwnie wyglądający
ciąg znaków, co wywoływało komunikat o błedzie. Zamieniłem tę wartość na
"1" i wszystko przeszło - byłem w stanie wygenerować kod.
Na początku miałem jakieś problemy ze stabilnością - kod się w pewnym
momencie zawieszał i przestawał wykonywać kod umieszczony w pętli
głównej tasku. Pomogło jednak zwiększenie rozmiaru przypisanego mu stosu.
Następnie wykonałem podstawowe testy peryferiów, inicjując je i
komunikując się z nimi z poziomu tasku. Zadziała zarówno karta SD/FatFS
jak i VS1003.
Natomiast trafiłem na jakiś problem z obsługą Ethernetu. Jeśli dobrze
rozumiem, w przypadku zastosowania FreeRTOS-a cała obsługa sieci powinna
się odbywać w tle, ponieważ sterownik Ethernetu otrzymuje swój własny,
prywatny task. Tymczasem po podłączeniu zasilania urządzenie nie pojawia
się wcale w routerze, jakby nie został mu przydzielony adres przez DHCP.
Co ciekawe jeśli spróbuję włączyć zasilanie przy odłączonym kablu
Ethernetowym, to zaraz po starcie mam następujący komunikat:
"Assertion "netif is not up, old style port?" failed at line 727 in
/Middlewares/Third_Party/LwIO/src/core/ipv4/dhcp.c"
Czyli jakaś próba uzyskania dostępu do DHCP jest podejmowana, ale
failuje (bo kabel jest odłączony). Przy podłączonym kablu nie mam tego
komunikatu. Tylko czemu w takim razie płytka nie dostaje adresu i nie
zaczyna się komunikować z siecią?
Coś jeszcze trzeba zrobić, żeby uzyskać działający Ethernet na FreeRTOS?
Atlantis
Guest
Wed Oct 26, 2022 6:55 am
Ok, zaczynam powoli podejrzewać, że wina może leżeć gdzieś po stronie
ustawień charakterystycznych dla FreeRTOS: priorytety, zarządzanie
pamięcią, rozmiar stosu.
Na początku zaobserwowałem podobny problem z biblioteką USB - chociaż
kod wykonywany w pętli głównego tasku działał, to nie byłem w stanie
dostać się do PenDrive'a - FatFS zgłaszał FR_DISK_ERR. Problem minął gdy
zwiększyłem rozmiar pamięci przeznaczonej do alokowania stosów tasków
oraz sam stos głównego tasku. Pendrive zaczął być wykrywany i mogłem
czytać zapisane na nim dane.
Podejrzewam, że z lwIP/Ethernetem sprawa również może leżeć w
konfiguracji systemu/pamięci. Niestety nie jestem w stanie zwiększać
ilości przydzielonej pamięci w nieskończoność, bo STm32F107 ma jej dość
ograniczoną ilość (64kB), która już teraz jest w dość znacznej części
zajęta.
Może ktoś jest w stanie zaproponować jakieś optymalne ustawienia?
Grzegorz Niemirowski
Guest
Wed Oct 26, 2022 8:02 am
Atlantis <marekw1986NOSPAM@wp.pl> napisał(a):
Quote:
Może ktoś jest w stanie zaproponować jakieś optymalne ustawienia?
Dlaczego po prostu nie weźmiesz jakiegoś gotowca i zobaczysz jak tam jest
zrobione?
--
Grzegorz Niemirowski
https://www.grzegorz.net/
Marek
Guest
Wed Oct 26, 2022 11:18 am
On Wed, 26 Oct 2022 08:55:17 +0200, Atlantis <marekw1986NOSPAM@wp.pl>
wrote:
Quote:
Ok, zaczynam powoli podejrzewać, że wina może leżeć gdzieś po
stronie
ustawień charakterystycznych dla FreeRTOS: priorytety, zarządzanie
pamięcią, rozmiar stosu.
Jak pamiętam łączyłem kiedyś MLA z FreeRTOS i faktycznie na prawdę
zacnie to pamięci potrzebowało na stos, nie żałuj.
--
Marek
Adam GĂłrski
Guest
Wed Oct 26, 2022 11:23 am
W dniu 26.10.2022 o 08:55, Atlantis pisze:
Quote:
Ok, zaczynam powoli podejrzewać, że wina może leżeć gdzieś po stronie
ustawień charakterystycznych dla FreeRTOS: priorytety, zarządzanie
pamięcią, rozmiar stosu.
Na początku zaobserwowałem podobny problem z biblioteką USB - chociaż
kod wykonywany w pętli głównego tasku działał, to nie byłem w stanie
dostać się do PenDrive'a - FatFS zgłaszał FR_DISK_ERR. Problem minął gdy
zwiększyłem rozmiar pamięci przeznaczonej do alokowania stosów tasków
oraz sam stos głównego tasku. Pendrive zaczął być wykrywany i mogłem
czytać zapisane na nim dane.
Podejrzewam, że z lwIP/Ethernetem sprawa również może leżeć w
konfiguracji systemu/pamięci. Niestety nie jestem w stanie zwiększać
ilości przydzielonej pamięci w nieskończoność, bo STm32F107 ma jej dość
ograniczoną ilość (64kB), która już teraz jest w dość znacznej części
zajęta.
Może ktoś jest w stanie zaproponować jakieś optymalne ustawienia? ;)
A zobacz czy czasem MAC nie jest ustawiony na 00:00:00:00:00:00.
Wtedy niby sieć powinna działać, ale z DHCP adresu nie dostaniesz.
Pozdrawiam
Adam Górski
Atlantis
Guest
Wed Oct 26, 2022 7:31 pm
On 26.10.2022 13:18, Marek wrote:
Quote:
Jak pamiętam łączyłem kiedyś MLA z FreeRTOS i faktycznie na prawdę
zacnie to pamięci potrzebowało na stos, nie żałuj.
I faktycznie - tutaj leżała przyczyna. Jeśli dobrze rozumiem FreeRTOS
(przynajmniej w wersji udostępnianej przez STM32CubeMX) nie alokuje
pamięci na stosy tasków ze sterty, ale używana jest do tego statycznie
wydzielona przestrzeń w RAM-ie o z góry określonej wielkości.
STM32Cube posiada wskaźnik stopnia zajętości tej przestrzeni,
najwyraźniej jednak bierze on pod uwagę tylko taski utworzone przez
użytkownika. Te wygenerowane automatycznie przez sterowniki nie są brane
pod uwagę, co jest mylące.
Wpadłem na to po tym gdy zorientowałem się, że zmniejszenie rozmiaru
stosu głównego tasku sprawiło, że sterownik USB nagle zaczął działać.
Zwiększyłem więc ilość pamięci na stosy o kilka kolejnych kB i wtedy
także Ethernet ruszył. :)
Teraz pozostało jeszcze przepisanie kodu aplikacji w taki sposób, aby w
pełni wykorzystać możliwości RTOS-a. Pierwsza rzecz to to oczywiście
zaimplementowanie socket API, ale poza tym trzeba będzie usunąć
mechanizmy oparte na programowaniu współbieżnym i zastąpić je kilkoma
taskami. Powinno się dość dobrze sprawdzić np. podczas przesyłania
danych do/z bufora.
Atlantis
Guest
Thu Oct 27, 2022 6:00 pm
Ok, jak wspominałem manipulując ustawieniami pamięci i rozmiarem stosu
głównego tasku udało mi się uruchomić Ethernet/lwIP. Płytka dostaje
adres IP od DHCP, pojawia się na liście na routerze oraz jestem w stanie
ją pingować.
Teraz zabrałem się za przepisywanie swojego kodu z użyciem Socket API.
Udało mi się uzyskać adres OP docelowego serwera za pomocą DNS-a (co
potwierdza, że łączność z siecią działa) jednak w tej chwili rozbijam
się przy próbie utworzenia socketu i połączenia z serwerem.
Funkcja lwip_socket zwraca -1, a zmienna errno jest ustawiana na wartość
105 (No buffer space available). Ktoś mógłby podpowiedzieć jakiego
bufora mu brakuje? I co powinienem zmienić w konfiguracji?
Generalnie przydałaby się tez informacja skąd mógłbym spróbować odzyskać
trochę pamięci, bo w chwili obecnej jej wykorzystanie (szacowane przez
STM32CubeIDE po kompilacji) przekroczyło już 86%.
Marek
Guest
Fri Oct 28, 2022 6:44 am
On Thu, 27 Oct 2022 20:00:58 +0200, Atlantis <marekw1986NOSPAM@wp.pl>
wrote:
Quote:
Generalnie przydałaby się tez informacja skąd mógłbym spróbować
odzyskać
trochę pamięci, bo w chwili obecnej jej wykorzystanie (szacowane
przez
STM32CubeIDE po kompilacji) przekroczyło już 86%.
I to był chyba główny powód, z którego FreeRTOS u mnie jak dotąd nie
znalazł zastosowania....
--
Marek
Atlantis
Guest
Wed Nov 02, 2022 9:16 pm
Ok, w chwili wolnego czasu udało mi się uruchomić część starego kodu na
tej płytce, za pomocą FreeRTOS-a. Zarówno lwIP jak i sterownik USB MSD
działają idealnie - wszystko czego potrzebowały to dość duże zwiększenie
rozmiaru sterty, z której są alokowane stosy dla poszczególnych tasków.
Zużycie pamięci RAM doszło w tej chwili do ponad 88%, ale urządzenie jak
na razie nie pokazuje oznak niestabilności wynikające z nadpisywania stosu.
Możliwość stosowania normalnych socketów momentalnie wyeliminowała
wszystkie problemy. Nawet streamy audio o nieco większym bitrate
odtwarzają się perfekcyjnie, a połączenia są stabilne. Odtwarzanie z
pendrive'a oraz karty SD również działa poprawnie, a pamieć SPI RAM
sprawdza się w roli bufora na odbierane dane.
Teraz pozostało mi do rozwiązania kilka problemów wynikających z
zastosowania samego RTOS-a.
Po pierwsze terowanie:
Bez systemu operacyjnego wszystko było proste - funkcje reagujące na
naciśnięcia przycisków czy kręcenie enkoderem były wykonywane w tej
samej pętli głównej. Miałem wiec absolutną pewność, że jeśli wykona się
funkcja wywołana naciśnięciem przycisku "stop" albo "next" to maszyna
stanów odpowiedzialna za odtwarzanie na chwilę obecną zakończyła
wykonywanie swoich operacji i mogę po prostu zmienić jej stan, zamknąć
połączenie i zainicjować następne albo przełączyć na odtwarzanie
kolejnego pliku.
Teraz sprawdzanie przycisków ma miejsce w innym tasku niż obsługa
maszyny stanów. Domyślam się, że nie mogę tak po prostu w dowolnym
momencie z innego tasku zamknąć połączenia, sprawdzić albo zmienić stanu
maszyny stanów obsługującej odtwarzanie. Jaki jest najlepszy sposób na
upewnienie się, że obsługa przycisków nie wywoła żadnej waznej funkcji
zanim w innym tasku nie zakończy się wykonywać VS1003_handle()?
heby
Guest
Wed Nov 02, 2022 10:04 pm
On 02/11/2022 21:16, Atlantis wrote:
Quote:
Jaki jest najlepszy sposób na
upewnienie się, że obsługa przycisków nie wywoła żadnej waznej funkcji
zanim w innym tasku nie zakończy się wykonywać VS1003_handle()?
FreeRTOS wspiera muteksy.
JDX
Guest
Thu Nov 03, 2022 7:22 am
Atlantis
Guest
Thu Nov 03, 2022 8:33 am
heby
Guest
Thu Nov 03, 2022 9:07 am
On 03/11/2022 08:33, Atlantis wrote:
Quote:
Na chwilę obecną przeszedł mi do głowy jeszcze pomysł, żeby zastosować
kolejkę wiadomości.
A w zasadzie jakiego multitaskingu używasz w tym FreeRTOS? Preemptive
czy cooperative?
Pewne rzeczy łatwiej zrobic w cooperative, ale do tego wymagana jest
higiena pisania kodu. Za to znikają problemy z synchronizacjami między
wątkami.
JDX
Guest
Thu Nov 03, 2022 3:02 pm
Marek
Guest
Thu Nov 03, 2022 8:57 pm
On Thu, 3 Nov 2022 09:07:39 +0100, heby <heby@poczta.onet.pl> wrote:
Quote:
Pewne rzeczy łatwiej zrobic w cooperative, ale do tego wymagana
jest
higiena pisania kodu. Za to znikają problemy z synchronizacjami
między
wątkami.
Heh no właśnie. Nie wspominając, że kooperatywie mniej pamięci zużyje
niż w FTOS. Idąc dalej.. to po co mu ftos? :)
--
Marek