lwIP - odbieranie danych przez TCP

Ok, przysiadłem jeszcze do tego projektu i udało mi się ustalić kilka kolejnych faktów:

  1. Byłem w błedzie co do pamięci SPI RAM. Z cała pewnością NIE JEST za wolna, żeby pełnić funkcję bufora. Przepisałem kod odpowiedzialny za odtwarzanie plików tak, żeby kierował dane z karty SD przez bufor cykliczny w tym zewnętrznym RAM-ie. Odtwarzanie jest całkowicie płynne. Oczywiście w teorii taki duży bufor w tym przypadku nie jest mi do niczego potrzebny, bo zarówno karta SD jak i pendrive są zupełnie stabilnymi źródłami danych, ale zostawię to jak jest - dla uproszczenia projektu.
  2. Przeniesienie bufora w całości do pamięci SPI pozwoliło mi odzyskać trochę wbudowanego RAM-u, którego część przeznaczyłem na powiększenie buforów lwIP. Robiłem to na wyczucie, wiec nadal nie wiem czy konfiguracja jest optymalna. Wygląda jednak na to, że sytuacja się poprawiła. Teraz jestem w stanie w czasie prawie rzeczywistym odtwarzać stream Radia Kraków w 32 kbps. "Prawie" bo raz na jakiś czas słychać zgrzyt.
  3. Natomiast stacje nadające w normalnej jakości (stereo i bitrate powyżej 100 kbps) są już potwornie poszatkowane.

Ponieważ odtwarzanie z karty SD przez bufor SPI RAM działa normalnie to wszystko wskazuje na to, że wina leży po stronie wolnej transmisji danych z Internetu. Nie chce mi się wierzyć, że wbudowany w STM32 FastEthernet MAC z PHY podłączonym przez RMII nie jest w stanie wyciągnąć tych trochę ponad 100 kbps (i z trudem wyciąga 32kbps). Zwłaszcza, że właściwie identyczny układ bez żadnych problemów działa na wcześniejszej konstrukcji z PIC32. Stawiałbym raczej na konfigurację stosu lwIP. Gdzie się będzie dało spróbuję jeszcze odzyskać w tym projekcie trochę RAM-u. Tymczasem ktoś mógłby mi może podpowiedzieć które opcje konfiguracyjne są najbardziej kluczowe z punktu widzenia odbierania streama audio? Co mogę wyłączyć, które wartości powinienem poddnieść, a które mogę zmniejszyć?

Jeśli projekt doczeka się kiedyś kolejnej iteracji to chyba już na jakimś STM32F4xx, o ile kiedyś znów będą dostępne w normalnych cenach. :)

Reply to
Atlantis
Loading thread data ...

IMO - samo sie dopasuje.

No to serwer poczeka, az mu sie uzupelni pula.. Czy raczej - jak sie uzbiera kolejna porcja danych audio, to program na serwerze ja wysle, a TCP albo wysle od razu, albo poczeka chwile - na potwierdzenie od odbiorcy. Tak czy inaczej - buforowanie po stronie serwera wydaje sie nie miec sensu. odbiorca niech sobie zbuforuje, zeby nie miec przerw w transmisji.

Tak swoja droga - dla masowych nadawcow typu radio czy TV krajowa ... jakos inaczej powinno byc to zorganizowane, przynajmniej tak mi sie wydaje. IP Multicast przeciez jakis byl przewidziany.

Na RMF roznica jest wieksza ... ale - to to twoje radio, gdzie program piszesz? wstepne wypelnienie bufora robisz, czy pchasz od razu w glosnik?

I to swietnie dziala z FTP czy inna transmisja plikow, gdzie dane do wyslania czekają. Radio, TV, czy chocby terminal - nie ma wiecej danych do wyslania. Chwilowo nie ma - za moment bedą.

nie znam tej biblioteki, ale brzmi, jakbys potrzebowal bufora kolowego na ... te wskazniki :-)

IMO niepotrzebne. Skoro i tak masz przerwe, to odegraj dane do konca. Po czym zatrzymaj odgrywanie, az sie bufor zapelni odpowiednio - 50% czy 90% ...

A jakie radio?

Bo wiekszosc na innych programach raczej nie ma problemow. Internet i serwery mamy dosc szybkie.

Czyli co - ten SPI RAM jakis wolny? Jaka to dokladnie kosc?

A moze ... na odczyty starczalo, na zapisy i odczyty juz nie starcza przepustowosci. Bo skoro RAM, to spodziewam sie, ze zapis jest szybki ...

J.

Reply to
J.F

Multicast nie przejdzie prze inteneret (oczywiście oprócz VPNnów, tunelów i innych MPLSów) Duzi nadawcy mogą użyć multicast to swoich PoP a tam unicastem do odbiorców. Taka Polska to taki jeden region w sumie - nie wiem czy jest sens kombinować.

c.

Reply to
Cezar

On 28.09.2022 09:30, Atlantis wrote: [...]

Nie zawsze to działa. Np. brytyjskie Absolute Radio nakłada ograniczenia geograficzne na większość z ich stacji i jeśli wykryje IP z poza UK, to pyta się o kod pocztowy. Wystarczy podać jakiś fejkowy kod z UK i działa. To oczywiście jeśli korzystasz z ich playera. Jeśli wydłubiesz konkretnego URL-a i zapodasz go do VLC, to już nie będzie działać. Na pewno da się to obejść, ale trzeba podłubać. Ja nie miałem czasu.

Reply to
JDX

Ale wlasnie o to chodzi - czy to nie powinno byc tak, ze nadawca emituje tylko kilka pakietow na kluczowe kierunki, a routery po drodze je rozmnazają?

Oczywiscie wymagalo by to raczej UDP.

J.

Reply to
J.F

Karta SD/pendrive niekoniecznie sa stabilnymi zrodlami danych, jak bedziesz na nie zapisywal.

Hm ... uzyj lepszy procek, Luke :-)

Dodaj pare diodek sygnalizujacych pusty bufor. Czy zapisuj jakies statystyki. A inne radia czy programy jak rozumiem sobie radzą? Bo bufor w programach bywa duzy, np 20s.

A jak z pamiecią? Bo wersja a) PIC mial wiekszy bufor, i na zacięcia starczało, wersja b) masz jakies straty pakietow, co w TCP owocuje przestojami ..

Albo po prostu zapomnij - grac moze komputer, laptop, telefon :-)

J.

Reply to
J.F

TCP window wlasnie.

Przy czym jak pisalem ... akurat w przypadku radia wydaje sie, ze serwer powinien miec bufor malutki, moze nawet zaden. Chyba, ze dla nowych klientow - zeby im szybko zapelnic bufor, i zeby im gralo od początku ..

J.

Reply to
J.F

No cóż. Wiele wynalazków sieciowych zostało porzuconych. Czy np. jakiś op nadaje w swojej sieci multimedia multikastem? Ja się nie spotkałem.

Reply to
Marek

Ok, dopisałem kilkanaście linijek kodu odpowiedzialnego za mierzenie ilości danych obieranych w serwera w ciągu sekundy. Po prostu sumuję każdą kolejną wartość p->tot_ten ze zmienną tymczasową, która co sekundę jest przepisywana do zmiennej trzymającej aktualną wartość pomiaru a potem zerowana.

Przeprowadziłem dwa pomiary podczas odbierania streamu radiowej Jedynki. Pierwszy był przy zakomentowanych operacjach zapisy do pamięci SPI RAM. Wychodził transfer na poziomie 21-25 kB/s (czyli 168-200 kbps). Wartość zgodna z bitratem typowego strumienia audio. Natomiast po odkomentowaniu tych operacji wartość spada do 5-11 kB/s (40-88 kbps) co tłumaczy przerywany dźwięk. Nie wiem na ile to ma znaczenie, ale dodatkowo widać, że w obydwu przypadkach na początku transmisja jest nieco szybsza i po kilku sekundach stabilizuje się wokół niższej wartości. Generalnie można już wyciągnąć kilka wniosków:

  1. Można całkowicie odrzucić tezę, że winę za spowolnienia ponosi projekt płytki i gubienie pakietów z powodu błędów na warstwie sprzętowej (interfejs RMII). Gdyby tak było, to efekt byłby widoczny cały czas.
  2. Operacja zapisu do pamięci SPI RAM ma wpływ na szybkość transferu danych. Jednak nie jest to raczej prosta zależność na zasadzie pamięci mającej niewystarczającą szybkość. Jak już mówiłem - ten bufor całkowicie normalnie działa z lokalnymi nośnikami, poza tym przy prędkości taktowania 18 MHz powinno być możliwe przesyłanie danych ze znacznie większą prędkością niż tych kilka kB/s. Poza tym problemy występowały też w przypadku stosowania (dużo mniejszego) bufora w normalnej pamięci.

Na chwilę obecną stawiałbym raczej na moją oryginalną tezę: w czasie gdy program jest zajęty zapisywaniem oryginalnego pakietu, Ethernet nie jest w stanie odebrać następnej porcji danych (bo kończy mu się jakiś bufor/okno odbiorcze) i dochodzi do retransmisji, która spowalnia realną prędkość przesyłu danych.

I teraz mam kilka pytań co do tego, jak właściwie działa Ethernet w STM32: Samo pobieranie danych z sieci do bufora odbiorczego jest realizowane w tle przez sprzęt, czy też pętla główna programu musi regularnie wywoływać jakiś sterownik? To znaczy jeśli bufor odbiorczy jest dostatecznie duży, to dane będą nadal dochodziły nawet wtedy, jeśli pętla główna będzie zajęta czymś innym?

Reply to
Atlantis

Teraz mi się przypomniało, że miałem podobne problemy z tym projektem, z socket buf na spiram nawet 128kB (używany wewnętrznie przez stos MLA) powodował po pewnej chwili buffer underrun a o wiele mniejszy bufor aplikacyjny na dane (ale nie socket buffer) w ram mcu dawał spokojnie radę.

Reply to
Marek

A czemu tak kurczowo się trzymasz MLA? Harmony też działa OK choć troszkę na początku sprawia wrażenie bardziej skomplikowanego. Ale jest bardzo podobny do MLA, nawet da się użyć uniwersalne wrapery by projekt poszedł przezroczyście na mla/Harmony.

Reply to
Marek

Jestem coraz mocniej przekonany, że winę za ten stan rzeczy może ponosić zbyt mały rozmiar bufora odbiorczego gniazda sieciowego. W momencie gdy aktualny pakiet jest przetwarzany (dane z niego są ładowane do pamięci SPI) brakuje miejsca na przyjęcie kolejnego i wymuszana jest retransmisja, powodująca w efekcie spowolnienie transmisji.

Przypomniałem sobie w międzyczasie, że bardzo podobny problem miałem na prototypie tej konstrukcji, pracującej na PIC24FJ256DA210. Tam też nie udało mi się uzyskać poprawnego odtwarzania streamów większych niż 32 kbps. Uznałem wtedy, że winę za to musi ponosić zbyt niskie taktowanie magistrali SPI, na której pracuje ENC28J60. Wtedy się nad tym za bardzo nie zastanawiałem, bo dysponowałem już nowsza wersją hardware'u. Jednak teraz z perspektywy czasu wydało mi się to dziwne, bo w końcu 16 MHz to nie mało.

Przypomniałem sobie także, że w tym projekcie na PIC24 także miałem problemy z pamięcią. Układ ma co prawda 96kB RAM-u, jednak korzystanie z niej nie jest takie oczywiste, bo tylko 32kB to dostępna bezpośrednio pamięć, w której może znajdować się stos i sterta. Reszta to specjalna pamięć stronnicowana, w której można umieszczać np. bufory ba dane. Jednak z uwagi na to, że trzeba z nią postępować w odpowiedni sposób, nie da się z niej bezpośrednio korzystać w standardowych bibliotekach. W pewnym momencie zacząłem mieć problemy, które interpretowałem jako nadpisywanie stosu. Pozmniejszałem więc rozmiary wszystkich buforów, które musiały się mieścić głównej pamięci - w tym buforów odbiorczych gniazd sieciowych.

Teraz przeprosiłem się z tym projektem na PIC24 i przyjrzałem mu się bliżej. Po pierwsze wykorzystałem tę dodatkową pamięć (EDS) do zaimplementowania 16kB bufora cyklicznego na dane audio. Już samo to pozwoliło mi zaoszczędzić trochę głównej pamięci. Po drugie wczytałem się trochę w opcje konfiguracyjne i zobaczyłem, że ten procesor ma ustawieni o nazwie "Data model", które może przyjmować wartość "small" lub "large". W "small" wszystkie zmienne statyczne oraz globalne muszą zmieścić się w pierwszych 8kB RAM-u. W "large" nie ma tego ograniczenia. Okazuje się, że to właśnie to ustawienie (a nie nadpisywanie stosu) powodowało u mnie problemy. Okazało się więc, że tak naprawdę mam jeszcze całkiem sporo "głównej" pamięci do zagospodarowania.

Pozwoliło mi to zwiększyć rozmiar bufora odbiorczego gniazda sieciowego do ponad 6kB. To zdecydowanie poprawiło sytuację. Streamy 192kbps nadal nie odtwarzają się poprawnie, ale te 128kbps i 160kbps już tak.

Reply to
Atlantis
2022-10-02 o 21:06 +0200, Atlantis napisał:

To chyba niezupełnie tak - stack ogłasza raczej okienko nie większe, niż rozmiar bufora gniazda, a zatem retransmisje z powodu "dostałem pakiet ale nie miałem gdzie go zapisać" nie powinny mieć miejsca. Oglądałeś połączenie pod jakimś wiresharkiem? Faktycznie widzisz tam retransmisje?

Stawiałbym raczej na zbyt małe okienko, a więc i niewielką ilość danych dostępnych z wyprzedzeniem, przez co jakikolwiek loss albo chwilowe opóźnienie uniemożliwia dalsze odtwarzanie.

To zaledwie 4 pakiety. Wychodzi coś w okolicach 400ms dźwięku - malutko.

Mateusz

Reply to
Mateusz Viste

Po pierwsze kwestia czasu - mam kilka pootwieranych projektów, które rozwijam niewielkimi krokami od kilku lat. To typowo hobbystyczne projekty, więc wszystko zależy od tego, czy znajdę czas i motywację. A jeśli już znajdę, to wolę go poświęcić na dodanie nowej funkcjonalności niż przepisywanie istniejącego kodu pod nowe biblioteki. Po drugie istniejące projekty są już na tyle rozbudowane, że mogę traktować je jako podstawę do tworzenia kolejnych. Wszystko co ma działać działa, jest dostępna bazowa funkcjonalność (np. konfiguracja przez WWW), więc jeśli chcę stworzyć jakiś szybki projekt, to wystarczy skopiować istniejący i zmodyfikować niektóre pliki. I to przedłużą życie MLA w moich projektach. Po trzecie - oryginalnie planowałem powolne przechodzenie na STM32 i biblioteki HAL, więc uczenie się Harmony wydawało mi się nie mieć za dużo sensu. Jednak koniec końców rozstanie się z PIC32 okazało się być trudniejsze niż sądziłem i nie tylko kontynuuję istniejące projekty na nich, ale też zdarzyło mi się zacząć kilka nowych, mniejszych.

Reply to
Atlantis

Ok, kompletnie nie mam pojęcia co może być powodem takiego zachowania projektu. Wyczerpałem już chyba wszystkie pomysły. Na chwilę obecną udało mi się sprawdzić następujące kwestie:

- Dodałem prosty kod do pomiaru ilości bajtów odbieranych w ciągu sekundy. Dzięki temu mogłem ustalić, że zaraz po połączeniu z serwerem nadającym stream mam transfer około 20 kB/s (co mniej-więcej pasuje do bitrate'u 192 kbps), jednak zaraz potem spada on do 1-2 kB i zaczyna się "czkawka". Bufor musi się przez dłuższą chwilę napełniać, żeby odtworzyć krótki fragment audio.

- Zakomentowałem wszystkie operacje zapisu odebranych danych do pamięci SPI RAM (w razie gdyby faktycznie to ona powodowała problemy). Po prostu od razu zwalniam bufor z odebranymi danymi i zgłaszam gotowość do odbierania kolejnych. I faktycznie - w tej sytuacji miałem ciągły transfer w okolicach 20 kB/s.

- Już pomyślałem, że winę faktycznie ponosi pamięć SPI, przygotowałem więc bufor cykliczny w zwykłej pamięci RAM. Implementacja nie jest może idealna, ale sprawdziła się już w innym projekcie (na PIC24). Bufor jest co prawda mały - testowałem wariant 4kB i 8kB - ale na wcześniejszych wersjach hardware'u tych kilka kB w zupełności wystarczało do płynnego odtwarzania. Niestety, po wgraniu tej wersji wrócił problem - prędkość dość szybko spada do 1-2 kB.

- Żeby było ciekawiej zarówno 128kB bufor w pamięci SPI, jak i 8kB bufor w zwykłym RAM-ie bez najmniejszego problemu sprawdzają się, gdy karmię je danymi z karty SD. Wtedy odtwarzanie działa całkowicie normalnie.

Podejrzewam, że winę musi ponosić mój własny bład, którego jednak za nic nie jestem w stanie namierzyć. Jeśli ktoś ma czas i ochotę żeby rzucić okiem, to aktualna wersja jest dotępna na GitHubie:

formatting link
Kluczowe miejsca:

Callback obsługujący odbieranie przychodzących danych:

formatting link
Miejsce w maszynie stanów, gdzie ładowane są dane do bufora, ale bez odtwarzania. Tutaj też realizowany jest opóźniony odbiór tych danych, których nie dało się odebrać w callbacku z uwagi na brak miejsca w buforze:
formatting link
To samo co powyżej, tylko podczas normalnego odtwarzania:
formatting link
Miejsce w którym do bufora cyklicznego ładowane są dane z systemu plików (karta SD lub pendrive):
formatting link

Reply to
Atlantis

To by wskazywalo na zbyt male bufory/okno danych. Sprzet wyraznie moze pracowac szybciej, ale kontrola przeplywu TCP mu nie pozwala. Ja bym sprawdzil co sie dzieje jak wywalisz caly kod odpowiedzialny za dzwiek i zostawisz tylko odbior strumienia, ale potwierdzajac w takim tempie (w przyblizeniu) jak kodek by je odbieral.

Jeszcze moze glupie pytanie: w jakim tempie piszesz/czytasz ten RAM SPI? DMA powinno przerzucac dane z maksymalna predkoscia SPI, ale RAM moze miec porabany protokol a jak go obsluzysz przez software to moga byc straty predkosci.

Pytanie kiedy potwierdzasz odbior: przed czy po zapisie do SPI RAM. Jesli po to potwierdzenie jest opoznione i efektywnie zmniejsza dostepne okno.

Pisales ze jest 6kB na bufory LWIP. To 4 pakiety maksymalnej wielkosci. Jesli 1 to wlasnie odbierany pakiet (nie wiem czy LWIP ma na niego oddzielny bufor) a 1 to pakiet ktory przerabiasz to zostaja 2 pakiety na buforowanie. Zaleznie od szybkosci to moze byc 250-150 ms buforowania. Niby moze dzialac ale ma prawo sie rwac.

Piszesz o jakims "buforze audio". Nie wiem co to ma byc, ale datasheet VS1003 mowi o przesylaniu bloku 32 bajtow, czyli w zasadzie jesli jest portrzebny jakis bufor to na poziomie max setek bajtow. Czyli pownny byc dziesiatki kilobajtow wolnej pamieci: STM32F107 ma 64KB RAM.

Moim zdaniem rozsadny projekt przydzielilby duzy kawalek pamieci dla LWIP. Tak na oko minimum 15KB (10 pakietow maksymalnej wielkosci). Przy 64KB RAM powinno byc mozliwe przydzielnie LWIP 40KB (zwykle przyjmuje sie ze implementacja TCP potrzebuje minimalnie 40KB do pracy, ty masz jeden strumien a LWIP powinien byc oszczedny, wiec moze bedzie dzialalo z mniejsza iloscia).

Przeplyw danych powiniem byc nastepujacy:

ETH -> bufor LWIP -> VS1003

Ewentualnie buforek powiedzmy 256 bajtow dla DMA pomiedzy STM a VS1003 (taki buforek, podzielony na polowki po 128 bajtow wystarcza zeby DMA pracowalo plynnie).

Ethernet ma swoje DMA ktore wrzuca pakiet do pamieci. Jak sie dzieje cos co wymaga uwagi procka to zglasza przerwania. Ten interfejs moze wrzucic dane do listy buforow (nie trzeba jednego ciaglego bufora). Czyli jak sa dostepne bufory to jest minimalne obciazenie procka. Ale kluczem jest dostepnosc buforow. Nie wiem jak to rozwiazuje LWIP. Jedna mozliwosc to kolejka buforow uzupelniana przez petle glowna, wtedy procedura obslugi przerwania pobiera bufory z kolejki (o ile sa dostepne). Ale mozna to robic inaczej.

Jeszcze jedna uwaga: w STM transmisje danych powinno robic DMA. "Dogladac" DMA powinny procedury obsugi przerwan. Normalny kod powinien sledzic stan polaczenia TCP, przygotowywac pakiety potwierdzenia (to robi LWIP) i robic zarzadanie "wysokopoziomowe". Wiekszosc operacji "petli glownej" powinna byc malo krytyczna czasowo. Najwiecej uwagi moim zdaniem wymaga generowanie potwierdzen (czyli wywolanie 'tcp_recved'), tak zeby miec wlasciwa wielkosc okna TCP.

Reply to
antispam

Które opcja w konfiguracji lwIP za to odpowiada? W stosie TCP/IP od Microchipa po prostu ustawiało się parametr określający wielkość bufora odbiorczego i nadawczego przy konfiguracji konkretnego socketu. W lwIP nie widzę czegoś takiego niestety.

Najbliższą rzeczą do tego jaką zrobiłem było wywalenie zapisywania nadchodzących danych do bufora cyklicznego. I wygląda na to, że wtedy leciały z maksymalną dostępną prędkością, odpowiadającą bitrate'owi streama. Nie bardzo wiem natomiast jak w przypadku lwIP narzucić tempo odpowiadające tempu zapotrzebowania na dane przez VS10xx. W przypadku stosu od Microchipa było to proste - przychodzące dane trafiały do bufora FIFO socketa, z którego mogłem je pobierać porcjami o dowolnej wielkości. Jeśli dobrze rozumiem w przypadku lwIP i RAW API jest inaczej

- mam obowiązek przyjąć całą porcję danych zgłoszoną przez callback odbiorczy, zwolnić pamięć i wywołać tcp_recved. Stąd potrzeba stosowania bufora cyklicznego.

Na chwilę obecną nie używam DMA - dane są po prostu przepisywane z jednego miejsca w drugie w pętli. Myślałem, że SPI może powodować opóźnienia, jednak tę hipotezę można już odrzucić ponieważ:

- Urządzenie zachowuje się identycznie w przypadku bufora cyklicznego w ulokowanego pamięci SPI, jak również (mniejszego) w zwykłym RAM-ie.

- Żadne problemy nie występują w przypadku odtwarzania z karty SD.

To tak można? ;) Myślałem, że tcp_recved() wolno mi wywołać dopiero po przetworzeniu odebranych danych i zwolnieniu pamięci za pomocą pbuf_free().

6kB to chyba było odnośnie wcześniejszej wersji urządzenia, zrealizowanej na PIC-u. Tam dość łatwo było ustawić konkretną wielkość bufora odbiorczego.

Dodatkowy bufor na dane audio, pośredniczący w komunikacji pomiędzy źródłem danych (Ethernet, lokalny nośnik pamięci) a VS10xx. Praktyka pokazała, że jego zastosowanie dość mocno zwiększa stabilność, zwłaszcza w przypadku Ethernetu. Implementowałem go do tej pory na jeden z dwóch sposobów:

- klasyczny bufor cykliczny

- Dwuczęściowy bufor. Gdy jedna część karmi dekoder MP3, druga jest ładowana danymi z zewnątrz. Potem następuje zamiana. To właśnie tę funkcję w projekcie pełni pamięć SPI RAM.

Reply to
Atlantis

Ciekawe co na to serwer - nie moze ci wyslac danych odpowiednio szybko, buforowac tez nie moze w nieskonczonosc - powinien gdzies u siebie przeskakiwac na aktualne dane.

Ogolna zasada TCP - serwer wysyla na początku kilka pakietow danych, dokladnie to TCP_window bajtow, a potem czeka na potwierdzenie pierwszego. W przypadku radia moze byc inaczej, jesli nie ma u siebie bufora danych. No ale nawet wtedy te ~20kB/s szybko uzbiera, a Ty nie nadążasz odebrac.

Z grubsza mozliwe, ale patrz nizej. A moze przerwania sa blokowane ?

Troche wątpie. Przy zgubieniu pakietu timeout sie wlacza, i to mogą byc grube sekundy. Chyba bys nie uzyskal 5-11 kB/s. No chyba, ze radio ma domyslnie jakies krotsze czasy. Algorytm doboru timeoutu w TCP dosc skomplikowany ... ale moze mozesz u siebie przetestowac - zasymuluj np zgubienie co setnego pakietu.

Raczej bym sie spodziewal problemu w jakims opoznieniu w wyslaniu potwierdzenia. Ale zeby az tak to SPI zwalniało? 18MHz wydaje sie sporo ... a ogladales oscyloskopem? Albo czy mierzyles przepustowosc/czas zapisu pakietu?

A w ogole ... masz tam jakies zabezpieczenie kolejnosci w tej bibliotece? Bo powiedzmy przychodzą pakiety nr 1, 2, 3, a nr 4 nie przychodzi. Ale przychodzi nr 5, 6, 7 ... i co wtedy - nie dostaniesz callbacka z nr 5, a bufory 5, 6, 7 zostaną skasowane ?

Ba, bez zadnych retransmisji moga przyjsc pakiety w kolejnosci

1, 2, 3, 5, 4, 6, 8, 7, itp.

J.

Reply to
J.F

I wszystko wskazuje na to, że tak to właśnie działa. Przynajmniej odnoszę wrażenie, że dźwięki które słyszę z przerwami nie są kolejnymi fragmentami tego samego strumienia audio, ale raczej "okienkami" które aktualnie udaje się odebrać.

Tak. Pytanie tylko dlaczego nie nadążam tego odebrać. Można było teoretyzować o niskiej przepustowości pamięci SPI RAM (co i tak było wątpliwe, bo 18 MHz to naprawdę szybka transmisja) ale ta teoria padła w momencie, gdy identyczny problem udało się stwierdzić także w przypadku zastosowania bufora cyklicznego w RAM-ie.

Jakie przerwania? W moim kodzie w ogóle nie używam przerwań związanych z Ethernetem. Używam gotowych sterowników dostarczanych przez producenta mikrokontrolera oraz gotowego stosu (lwIP). W rozsądnym projekcie użytkownik nie powinien w ogóle przejmować się przerwaniami - powinny one w tle ładować dane do jakiegoś FIFO. Zresztą nigdzie w dokumentacji nie znalazłem ani jednej wzmianki o przerwaniach. O ile informacje na jakie udało mi się trafić w Internecie są poprawne, to procedura odbioru jest następująca:

- Stos wywołuje zarejestrowana wcześniej funkcję obsługi callbacku odbiorczego.

- Do tej funkcji przekazywany jest wskaźnik na struct pbuf. Struktura zawiera dynamicznie alokowany bufor na payload. Może też zawierać wskaźniki do kolejnych struktur tego samego typu.

- Z jednej lub kilku struktur trzeba pobrać dane i gdzieś je zapisać.

- Jeśli już skończyliśmy tę operację, wywołujemy pbuf_free() aby zwolnić pamięć oraz tcp_recved() aby zwiększyć rozmiar okna (poinformować serwer, że może przesłać więcej).

U mnie może się zdarzyć sytuacja, że otrzymanych danych będzie więcej niż miejsca w buforze. Wtedy nie mogę ich odebrać od razu - muszę się z tym wstrzymać do czasu, aż dekoder MP3 wyjmie z bufora odpowiednią ilość danych. Wtedy odbiór tej konkretnej paczki jest opóźniony i odbywa się w pętli głównej.

W żadnym miejscu nie mam do czynienia z przerwaniami.

Kiedy transmisja zaczyna mulić to nie jest 5-11 kB/s, a 0-2kB/s.

Nie, bo wydawało mi się to nie mieć sensu. Udało mi się ustalić, że wina nie leży po stronie pamięci SPI. Przemawiają za tym dwa argumenty:

- Pamięć SPI doskonale sprawdza się przy buforowaniu streama z karty SD.

- Ten sam problem występuje, jeśli dane przychodzące przez TCP próbuję zapisywać do bufora cyklicznego ulokowanego w zwykłym RAM-ie.

Wydaje mi się, że przecież chyba TCP ogarnia kwestię pakietów przychodzących w złej kolejności i użytkownik nie musi się przejmować tą kwestią podczas pisania aplikacji. Ten problem pojawia się dopiero w przypadku zastosowania UDP. Tak czy inaczej lwIP ma opcję związana właśnie z tą kwestią. Jeśli dobrze rozumiem to można wybrać jak ma się zachować stos. W przypadku zgubienia któregoś z pakietów w sekwencji można albo trzymać nadmiarowe do momentu otrzymania brakującego, albo poprosić jeszcze raz o wysłanie całej sekwencji licząc, że tym razem przyjdą wszystkie i po kolei. Próbowałem obydwu ustawień.

Swoją drogą, czy ktoś może mi wyjaśnić w jaki sposób skonfigurować lwIP, żeby mieć dostatecznie duży bufor odbiorczy? W stosie od Microchipa po prostu ustawiało się wielkość bufora nadawczego i odbiorczego dla konkretnego gniazda. Tutaj cała masa opcji, które nic mi wprost nie mówią...

formatting link

Reply to
Atlantis

A czy problemy z odtwarzaniem przez sieć nie wynikają ze słabej wydajności stosu tcpip iwip/mla przy "odległych" podłączeniach? Np. MLA szybko działa w lokalnej sieci (kilkaset kB/s) ale przez internet jest już znacznie wolniejszy (kilka kB/s) niż oczekiwany wpływ szybkości łącza. Problem rozwiązuje uzycie lokalnego proxy: gdy łączymy się z internetu do mcu przez lokalne proxy np. raspi szybkość pozostaje zachowana jak przy połączeniu lokalnym. Czy ktoś się domyśla z czego to wynika?

Czy próbowałeś odtwarzać przez lokalne proxy? Odwrotna sytuacja niż opisana wyżej. Uruchomić proxy do oryginalnego streamu na lokalnym komputerze w tym samym segmencie sieci co jest player na iwip/mla i niech ten player pobiera stream z proxy w lokalnej sieci a nie bezpośrednio z urla z internetu.

Reply to
Marek

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.